1

为什么这段代码

int (*g)(int);
int (*h)(char);
h = g;

在 C 中,编译时给我这样的警告:

'警告:来自不兼容指针类型的赋值'

在 C++ 中,无法编译。

4

8 回答 8

6

原型不匹配。g是一个指向一个函数的指针,该函数接受一个int并返回一个int,而h一个指向一个函数的指针,该函数接受一个char并返回一个int。它们是两种不同的类型,因此是警告(将苹果分配给橙子)。

于 2009-10-29T09:22:00.203 回答
3

这两个函数指针没有相同的签名,因为输入参数不同。

函数指针都返回一个int,而g接受一个int作为输入,而h接受一个char作为输入参数。

尽管您有时可以混合使用 intchar,但您正在混合函数指针,因此编译器会正确地向您发出警告,表明您可能做错了什么。

示例代码:

#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)'
于 2009-10-29T09:22:16.033 回答
2

一个声明指向接受 a 的函数int,另一个声明指向接受 a 的函数char。这些是不同的签名,因此指针不兼容。

于 2009-10-29T09:21:32.883 回答
1

您已将 g 声明为一个函数,该函数接受一个 int 类型的参数并返回一个 int,而 h 是一个接受一个 char 类型的参数并返回一个 int 结果的函数。这两个函数签名不可互换,因此您不能将指向一个的指针分配给指向另一个的指针。

于 2009-10-29T09:21:53.310 回答
0

您已将 g 和 h 声明为函数。实际上,我的编译器给出了错误“需要左值作为赋值的左操作数”,你可以只用一个警告来编译这段代码似乎很奇怪?

编辑:最初,问题中的代码将 g 和 h 声明为函数。现在它们已更改为函数指针,这确实只会发出警告。

于 2009-10-29T09:21:59.153 回答
0

因为您分配了不兼容的指针。一个函数指针将带符号整数作为参数,另一个 char (符号取决于您的系统)。即使两者返回相同,它们也是完全不同的。

忽略警告,使用函数指针(在进行强制转换以使其实际编译时),你会明白我的意思:)

于 2009-10-29T09:24:51.080 回答
0

由于函数签名不同,这不是合法的 C 或合法的 C++。问题是为什么编译器会以不同的方式对待它。这两个标准都没有关于如何处理违反标准的程序的指导,除了某些违反需要诊断(并且这两种情况都提供诊断消息)。这些标准通常关注什么是有效的 C 或 C++ 程序,以及在给定程序时实现必须做什么。

C 是一种比 C++ 更古老的语言,并且很多 C 代码是在比现在更不严格的编译器上编写的。C++ 从一开始就更严格,因此预标准 C++ 代码往往是有效的标准 C++ 代码,只是不使用某些功能。

出于这个原因,假设编译器是为实际使用而编写的,C 编译器比 C++ 编译器更宽松。毕竟,有很多 C 代码愉快地假设像这样工作,其中一些非常有用,但 C++ 并非如此。

于 2009-10-29T14:12:33.663 回答
0

我可以补充的是,C 中的函数匹配与 C++ 中的不同。在 C 中,您只使用名称(因此参数重载是不可行的)。在 C++ 中,每个函数都有不同的“签名”,由参数组成。(他们必须实现参数重载。)。

于 2011-08-30T15:06:04.120 回答