不兼容的指针类型(双指针)
Incompatible pointer types (double pointers)
在一个要求像这样的双指针的函数中:
#include <stdlib.h>
void prueba(void **ap)
{
*ap = NULL;
}
主要编译如下:
#include <stdlib.h>
#include <stdio.h>
void prueba(void **ap);
int main(void)
{
char *str;
str = (char *)malloc(sizeof(char) * 5);
prueba(&str);
if (str == NULL)
printf("NULL");
return (0);
}
我用 gcc 收到这个警告:
main2.c:11:9: warning: incompatible pointer types passing 'char **' to parameter of type 'void **' [-Wincompatible-pointer-types]
prueba(&str);
^~~~
main2.c:4:23: note: passing argument to parameter 'ap' here
void prueba(void **ap);
但是如果我用简单的指针做同样的事情,那就是将一个指向 char 的指针指向一个要求 void 指针的函数,gcc 会在没有警告的情况下进行编译,例如,以下编译正确:
功能:
#include <stdlib.h>
void prueba(void *ap)
{
ap = NULL;
}
主要内容:
#include <stdlib.h>
#include <stdio.h>
void prueba(void *ap);
int main(void)
{
char *str;
str = (char *)malloc(sizeof(char) * 5);
prueba(str);
if (str == NULL)
printf("NULL");
return (0);
}
所以我的问题是,为什么它适用于简单指针,但不适用于双指针(我猜是更大的指针)?
A void *
可以自由分配给任何对象指针或从任何对象指针自由分配。这种自由 不会 扩展到 void **
,因为那是一种独特的类型。
此外,您的固定程序将无法按预期工作,因为 ap = NULL;
仅更改 prueba
内部的局部变量,而不更改传入的参数。
更改您的原始程序以接受 char **
而不是 void **
。
根据 C 标准(6.3.2.3 指针)
1 A pointer to void may be converted to or from a pointer to any
object type. A pointer to any object type may be converted to a
pointer to void and back again; the result shall compare equal to the
original pointer.
所以在第二个代码片段中,类型 char *
的指针被隐式转换为类型 void *
尽管该函数没有意义,因为它处理其参数的副本,因此不改变原来的指针。
但是 void **
类型与 void *
类型不同。因此引号不适用于 void **
类型并且编译器发出诊断消息,因为没有从指向任何对象类型的指针到类型 void **
.[=17= 的指针的隐式转换]
在一个要求像这样的双指针的函数中:
#include <stdlib.h>
void prueba(void **ap)
{
*ap = NULL;
}
主要编译如下:
#include <stdlib.h>
#include <stdio.h>
void prueba(void **ap);
int main(void)
{
char *str;
str = (char *)malloc(sizeof(char) * 5);
prueba(&str);
if (str == NULL)
printf("NULL");
return (0);
}
我用 gcc 收到这个警告:
main2.c:11:9: warning: incompatible pointer types passing 'char **' to parameter of type 'void **' [-Wincompatible-pointer-types]
prueba(&str);
^~~~
main2.c:4:23: note: passing argument to parameter 'ap' here
void prueba(void **ap);
但是如果我用简单的指针做同样的事情,那就是将一个指向 char 的指针指向一个要求 void 指针的函数,gcc 会在没有警告的情况下进行编译,例如,以下编译正确: 功能:
#include <stdlib.h>
void prueba(void *ap)
{
ap = NULL;
}
主要内容:
#include <stdlib.h>
#include <stdio.h>
void prueba(void *ap);
int main(void)
{
char *str;
str = (char *)malloc(sizeof(char) * 5);
prueba(str);
if (str == NULL)
printf("NULL");
return (0);
}
所以我的问题是,为什么它适用于简单指针,但不适用于双指针(我猜是更大的指针)?
A void *
可以自由分配给任何对象指针或从任何对象指针自由分配。这种自由 不会 扩展到 void **
,因为那是一种独特的类型。
此外,您的固定程序将无法按预期工作,因为 ap = NULL;
仅更改 prueba
内部的局部变量,而不更改传入的参数。
更改您的原始程序以接受 char **
而不是 void **
。
根据 C 标准(6.3.2.3 指针)
1 A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
所以在第二个代码片段中,类型 char *
的指针被隐式转换为类型 void *
尽管该函数没有意义,因为它处理其参数的副本,因此不改变原来的指针。
但是 void **
类型与 void *
类型不同。因此引号不适用于 void **
类型并且编译器发出诊断消息,因为没有从指向任何对象类型的指针到类型 void **
.[=17= 的指针的隐式转换]