Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
指向函数赋值的指针,C_C_Pointers_Function Pointers - Fatal编程技术网

指向函数赋值的指针,C

指向函数赋值的指针,C,c,pointers,function-pointers,C,Pointers,Function Pointers,我不明白为什么以下代码会生成警告: int func(double a, int b, char c) { return 0; } int main() { int(*myPointer)() = func; return 0; } 我认为在C语言中,参数列表为空的函数意味着可以接收未知数量参数的函数。func4碰巧接收到3个参数。那么为什么它与myPointer不兼容呢 尤其令人困惑的是,以下内容在没有警告的情况下编译: void boo() { retur

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

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;
}

发生了什么事?

这是您收到的警告:

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


您正在通过
void
,这意味着需要强制转换。您应该使用正确的类型。

IIRC C编译器有某些假设,这些假设可能会导致非常奇怪的错误,因为您没有告诉它在调用该函数时需要多少堆栈空间。特别是由于定义不匹配,这可能会允许有人无意中读取函数指针声明并假定没有参数,从而使函数返回垃圾。如果您真的想要获取可变数量的参数,请使用my_func(…)和varargs。

这两种情况之间的区别如下所述:如果您将参数传递给一个不接受任何参数的函数,则只会消耗堆栈上的一些内存。如果不向接受少量参数的函数传递任何参数,后者将从堆栈中读取随机数据

更新:更改为社区wiki,以添加来自Pascal Cuoq的以下更正:


函数指针在两个方向上的强制转换是合法的,尽管编译器发出了警告。在这两种情况下,使用错误的原型调用函数都是非法的。一些ABI要求函数清理堆栈,在这种情况下,将参数传递给不接受任何参数的函数肯定会损坏堆栈,就像不将参数传递给期望它们的函数一样

C99,3.3.2.3标准杆。8:

指向一种类型函数的指针可以转换为指向 功能的另一种类型,并再次返回;结果应进行比较 等于原始指针。如果使用转换的指针调用 类型与指向的类型不兼容的函数 行为是未定义的


在C中,空参数列表表示函数不接受任何参数。我认为您将空参数列表与varargs混淆了

将第一个示例更改为包含参数将删除警告

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

警告就是警告。诚实的


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

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

比较两者:

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


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

否,具有空参数的函数是一个不接收任何参数的函数。您会收到什么警告?两者在gcc-4.3.4中给出相同的警告。什么是编译器?这是真的…你能解释一下自动升级变量是什么意思吗?在我看来,这样的前向声明是值得避免的。维护它们会让人困惑,尤其是当它们被提取到头文件中时。因此,一般来说,“指向接收参数的函数的指针”类型的指针指向不接收参数的函数是合法的,但“指向不接收参数的函数的指针”类型的指针是不合法的指向确实接收参数的函数?尽管编译器发出了合法的信息性警告,但函数指针在两个方向上的强制转换都是合法的。在这两种情况下,使用错误的原型调用函数都是非法的。一些ABIS命令函数清理堆栈,在这种情况下,将参数传递给接受不损坏堆栈的函数,当然不会将参数传递给期望My.C99 3.3.2.3 PAR的函数。8:指向一种类型函数的指针可以转换为指向另一种类型函数的指针,然后再转换回来;结果应与原始指针进行比较。如果转换的指针用于调用类型与指向类型不兼容的函数,则行为是未定义的。“在C++中,空参数列表意味着函数不带任何参数。”
int func();
int func(double a, int b, char c) 
{
    return 0;
}