我有以下版本的2D数组作为指针传递。
版本1
#include <stdio.h>
void disp(int a[][5])
{
printf("a[0][3] = %dn", a[0][3]); /* a[0][3] = 4 */
}
int main ()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
disp(a);
return 0;
}
#include <stdio.h>
typedef void(*callDisplay)(int*);
void disp(int a[][5])
{
printf("a[0][3] = %dn", a[0][3]); /* a[0][3] = 4 */
}
int main ()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
callDisplay fn = (callDisplay) &disp;
fn(a);
return 0;
}
版本1按预期上升警告incompatible pointer type. expected int (*)[5] but argument is of type int *
。然而,(版本2)使用指针调用相同的函数在编译时没有任何此类警告。
gcc options: gcc -O0 -g3 -Wall -c -fmessage-length=0
谁能解释一下这个?
如果在赋值函数指针时删除强制类型转换,则会得到:
tmp.c: In function ‘main’:
tmp.c:13:22: warning: initialization from incompatible pointer type [enabled by default]
callDisplay fn = &disp;
强制类型转换抑制此警告,即使通过强制类型转换到不同类型的函数指针,在调用函数指针时调用了未定义行为。基本上,你不需要强制转换函数指针,因为它会隐藏任何类似的警告。
如果你修复了函数指针,你会得到以下代码:
typedef void(*callDisplay)(int[][5]);
void disp(int a[][5])
{
printf("a[0][3] = %dn", a[0][3]); /* a[0][3] = 4 */
}
int main ()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
callDisplay fn = &disp;
fn(a);
return 0;
}
当您编译时,您会得到与第一个示例相同的警告:
tmp.c: In function ‘main’:
tmp.c:14:5: warning: passing argument 1 of ‘fn’ from incompatible pointer type [enabled by default]
fn(a);
^
tmp.c:14:5: note: expected ‘int (*)[5]’ but argument is of type ‘int *’
此函数声明
typedef void(*callDisplay)(int*);
当像
那样调用时,
有兼容的参数
fn(a);
这个问题与这个类型转换有关
callDisplay fn = (callDisplay) &disp;
这是错误的。
即程序有未定义的行为。
根据C标准(6.3.2.3指针)
指向某一类型函数的指针可以转换为指向某一类型函数的指针另一种类型的功能,然后再返回;结果要比较等于原来的指针。转换后的指针用于调用类型与引用类型不兼容的函数;