我有以下版本的2D数组作为指针。
版本1
#include <stdio.h>
void disp(int a[][5])
{
printf("a[0][3] = %d\n", 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;
}
版本2
#include <stdio.h>
typedef void(*callDisplay)(int*);
void disp(int a[][5])
{
printf("a[0][3] = %d\n", 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选项:gcc -O0 -g3 -Wall -c -fmessage-length=0
有人可以通过这个吗?
答案 0 :(得分:2)
如果在分配函数指针时删除了强制转换,则得到:
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] = %d\n", 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 *’
答案 1 :(得分:2)
此功能声明
typedef void(*callDisplay)(int*);
在调用
时具有兼容参数fn(a);
问题与此演员有关
callDisplay fn = (callDisplay) &disp;
这是错误的。
这是程序有未定义的行为。
根据C标准(6.3.2.3指针)
8指向一种类型的函数的指针可以转换为指向的指针 另一种类型的功能又回来了;结果应该比较 等于原始指针。 如果使用转换后的指针 调用一个类型与引用类型不兼容的函数, 行为未定义。