为什么这段代码
int (*g)(int);
int (*h)(char);
h = g;
在C中,编译时给我这样的警告:
“警告:来自不兼容指针类型的赋值”
在C++中,无法编译。
原型不匹配。
g
是指向接受 int
并返回 int
的函数的指针,而 h
是指向接受 char
并返回 int
的函数的指针。它们是两种不同的类型,因此会出现警告(将苹果分配给橙子)。
两个函数指针不具有相同的签名,因为输入参数不同。
函数指针都返回 int,而 g 接受 int 作为输入,h 接受 char 作为输入参数。
虽然您有时可以混合使用 int 和 char,但您正在混合函数指针,因此编译器会正确地向您发出警告,表明您可能做错了什么。
示例代码:
#include <stdio.h>
int gf(int n)
{
return printf("gf(%d)\n", n);
}
int hf(char c)
{
return printf("hf('%c')\n", c);
}
int main()
{
int (*g)(int) = gf; // pointer to gf
int (*h)(char) = hf; // pointer to hf
g = h; // warning: possibly incompatible functions
g(65); // cast 65 to char and call h
return 0;
}
编译:
$ gcc-4.exe -Wall a.c
a.c: In function 'main':
a.c:18: warning: assignment from incompatible pointer type
运行程序:
$ ./a.exe
hf('A')
如您所见,在 C 语言中,它工作得很好,但编译器会给您一个适当的警告。 如果我们尝试将其编译为 C++ 代码,编译器将不会接受我们的指针杂耍:
$ g++-4.exe a.c
a.c: In function 'int main()':
a.c:18: error: invalid conversion from 'int (*)(char)' to 'int (*)(int)'
一个被声明为指向接受
int
的函数,另一个 - 指向接受 char
的函数。这些是不同的签名,因此指针不兼容。
您已将 g 声明为采用一个 int 类型参数并返回 int 类型的函数,并将 h 声明为采用一个 char 类型参数并返回 int 结果的函数。这两个函数签名不可互换,因此您不能将指向一个的指针分配给指向另一个的指针。
您已将 g 和 h 声明为函数。实际上,我的编译器给出了错误“需要左值作为赋值的左操作数”,并且您可以仅通过警告来编译此代码,这似乎很奇怪?
编辑:最初,问题中的代码将 g 和 h 声明为函数。现在它们已更改为函数指针,这确实只会发出警告。
因为您正在分配不兼容的指针。一个函数指针采用有符号整数作为参数,另一个函数指针采用字符(符号取决于您的系统)。尽管两者返回相同,但它们却截然不同。
忽略警告,使用函数指针(同时进行转换以使其实际编译),你就会明白我的意思了:)
由于函数签名不同,这不是合法的 C 或合法的 C++。 问题是为什么编译器会以不同的方式对待它。 在这两个标准中都没有太多关于如何处理违反标准的程序的指导,除了某些违规行为需要诊断(并且这两种情况都提供了诊断消息)。 这些标准通常关注什么是有效的 C 或 C++ 程序,以及给定一个程序时实现必须做什么。
C 是一种比 C++ 更古老的语言,大量 C 代码是在比现在严格得多的编译器上编写的。 C++ 从一开始就更加严格,因此标准前的 C++ 代码往往是有效的标准 C++ 代码,只是不使用某些功能。
因此,假设编译器是为实际使用而编写的,C 编译器可能比 C++ 编译器更宽松。 毕竟,有很多 C 代码愉快地假设这样的事情可以工作,其中一些非常有用,但 C++ 却并非如此。
我要补充的是,C 中的函数匹配与 C++ 中的不同。在 C 中,您仅使用名称(因此参数重载是不可行的)。在 C++ 中,每个函数都有一个不同的“签名”,由参数组成。 (他们必须实现参数重载。)。