函数指针赋值,C语言

5

我不明白为什么以下代码会产生警告:

int func(double a, int b, char c)
{
    return 0;
}
int main()
{
    int(*myPointer)() = func;
    return 0;
}

我认为在C语言中,一个没有参数列表的函数意味着这个函数可以接收未知数量的参数。func4恰好接收了3个参数。那么为什么它与myPointer不兼容?

特别令人困惑的是,下面的代码编译时没有警告:

void boo()
{
     return;
}
int main()
{
    int(*pointerDude)(double) = boo;
    return 0;
}

发生了什么事?


1
不,带空参数的函数是一个不接收任何参数的函数。 - user405725
1
你收到了什么警告? - Daniel A. White
2
示例1示例2在gcc-4.3.4上都会产生相同的警告。这是哪个编译器? - Alok Save
6个回答

1
两种情况之间的区别可以这样解释:如果你向一个不接受参数的函数传递了一个参数,那么你只是在栈上消耗一些内存。如果你不向一个接受几个参数的函数传递任何参数,后者将从栈上读取随机数据。
更新:改为社区Wiki以添加来自Pascal Cuoq的修正:
在两种情况下,函数指针的强制转换是合法的,尽管会导致编译器发出警告。使用错误原型调用函数在两种情况下都是非法的。一些ABI要求函数清理栈,在这种情况下,向不接受参数的函数传递参数会像不向期望参数的函数传递参数一样破坏栈。
C99 6.3.2.3 第8段:
指向一种类型的函数的指针可以被转换为指向另一种类型的函数的指针,然后再转回来;结果必须与原始指针相等。如果使用转换后的指针调用与所指类型不兼容的函数,则行为未定义。

一般来说,指向“接收参数的函数指针”的指针可以指向不接收参数的函数,但是指向“不接收参数的函数指针”的指针不能指向接收参数的函数,这是合法的吗? - azphare
函数指针的强制类型转换在两个方向上都是合法的,尽管编译器会发出警告。在这两种情况下,使用错误原型调用函数都是非法的。一些 ABIs 规定函数清理堆栈,在这种情况下,将参数传递给不接受参数的函数会像不传递参数给期望参数的函数一样破坏堆栈。 - Pascal Cuoq
C99 6.3.2.3第8段:一个指向某种类型函数的指针可以被转换为指向另一种类型函数的指针,然后再转换回来;结果应该与原始指针相等。如果使用转换后的指针调用其所指向类型不兼容的函数,则行为是未定义的。 - Pascal Cuoq

0

我认为问题与参数的强制转换有关,因为char不是32位。请注意,如果将char更改为int,则可以正常工作。这与变量的自动提升有关。

比较这两个:

int func();
int func(double a, int b, int c) 
{
    return 0;
}

并且

int func();
int func(double a, int b, char c) 
{
    return 0;
}

gcc 对第二个会发出警告,但不会对第一个发出警告


那是真的...你能解释一下什么是变量的自动提升吗? - azphare
在我看来,像这样拥有前向声明是值得避免的。它们很难维护,特别是如果它们被提取到头文件中。 - Rontologist

0

你会得到以下警告:

警告:初始化不兼容的指针类型

你正在传递 void,这意味着需要一个强制类型转换。你应该使用正确的类型。


0
据我所知,C编译器有一些假设,可能会导致非常奇怪的错误,因为您在每次调用该函数时都没有告诉它需要多少堆栈空间。特别是由于定义不匹配,这可能会让某些人无意中读取您的函数指针声明,并假定没有参数,并且函数返回垃圾值。如果您确实想要使用可变数量的参数,请使用my_func(...)和varargs。

0

警告只是一个警告。真的。

在这种情况下,编译器知道您有一个不正确的函数指针类型,并且它明确告诉您。如果您尝试传递与3不同的参数数量,则会发出错误。


-1
在C语言中,空参数列表表示该函数不需要任何参数。我认为你把空参数列表和可变参数搞混了。
将你的第一个示例更改为包含参数将消除警告。
int func(double a, int b, char c)
{
    return 0;
}
int main()
{
    int(*myPointer)(double, int, char) = func;
    return 0;
}

2
在C语言中,空参数列表表示该函数不接受任何参数。 - Pascal Cuoq
1
你说的在C++中是正确的,但在C中不是。 - Kos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接