获取除 void * 之外的不兼容指针类型警告

Get incompatible-pointer-types warning except void *

#include <stdio.h>

void fun1(int *c){return;}
void fun2(void *p){return;}
void fun3(void **p){return;}

typedef void (* myfunptr)(void *);

void fun4(myfunptr b){
return;
}

    int
    main(){
    
       int *p;
       void *q = p;
    
       fun1(p); //no warning
    
       fun1(q); //no warning
    
       fun2(p); //no warning
    
       fun2(q); //no warning
    
       fun3(&p); //warning - incompatible pointer types
    
       fun3(&q); //no warning
       
       fun4(fun1); //warning - incompatible pointer types
    
       fun4(fun2); //no warning 
    
       return 0;
    
    }

我在 fun3(&p) 意识到警告,因为 void ** 不是像 void * 这样的通用指针。但是,我有点疑惑为什么在fun4(fun1)的情况下会有警告,因为void *int *是在没有警告的情况下隐式转换的。

我的下一个问题是,对于所有不兼容的指针转换,我会收到“不兼容类型”的警告,除非涉及 void *void **。因为使用 -Wno-incompatible-pointer-types 会禁用所有类型转换的警告。

虽然 int* 可以隐式转换为 void*(如您所说,没有警告),但 fun4(fun1); 语句的情况却大不相同。在这种情况下,您正在隐式转换 函数指针 – 在指向具有 不同签名 .

的函数的指针之间

关于指向不同类型函数的指针之间的兼容性的更全面的讨论可以在这里找到:Casting a function pointer to another type

虽然,在您的特定情况下,通过 fun4 指针参数调用 fun1 应该 没有问题(因为,如您所说,前者有一个与为 fun4 参数提供的参数列表兼容的参数列表),编译器仍然(恕我直言)'justified' 向您提供警告,即 fun1 的签名不同于对于预期的 myfunptr.

fun1(p); //no warning

int* 显然兼容 int*

fun1(q); //no warning

void*,作为一种特殊情况类型,与所有其他对象指针类型兼容,并隐式转换 to/from 其他指向对象类型的指针。

fun2(p); //no warning

如前所述,void*int* 可以相互隐式转换 to/from。

fun2(q); //no warning

void* 显然兼容 void*

fun3(&p); //warning - incompatible pointer types

void* 的特殊规则不适用于“递归”。 void** 不是通用对象指针类型。它与 int** 不兼容。您会看到一些无用的 API 仍在进行此类转换(CUDA 等),但它们很糟糕并且依赖于非标准行为。

fun3(&q); //no warning

void** 显然兼容 void**.

fun4(fun1); //warning - incompatible pointer types

函数指针需要指向相同的函数才能兼容。相同的 return 类型、相同的参数、相同的限定符。

fun4(fun2); //no warning

您提供了预期类型的​​函数指针,所以没问题。请注意 fun2 在这种情况下从函数“衰减”为函数指针,因为它用在表达式中。


另请注意,void* 是通用的 object 指针。您不能将它用作通用指针类型来与函数指针混合使用!