不兼容的指针类型(双指针)

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= 的指针的隐式转换]