指向函数赋值的指针,C

发布于 2024-12-02 15:48:40 字数 422 浏览 1 评论 0原文

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

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

发生了什么事?

I don't understand why the following code generates a warning:

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

I thought that in C, a function with an empty parameters list mean a function that can receive an unknown number of parameters. func4 happens to receive 3 parameters. So why is it incompatible with myPointer?

Its especially confusing because the following does compile without warning:

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

What's going on?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

人海汹涌 2024-12-09 15:48:40

这两种情况之间的区别可以这样解释:如果将参数传递给不接受任何参数的函数,那么您只是消耗了堆栈上的一些内存。如果您不将任何参数传递给接受一些参数的函数,则后者将从堆栈中读取随机数据。

更新:更改为社区 wiki,添加 Pascal Cuoq 的这些更正:

尽管编译器会发出警告,但函数指针在两个方向上的转换都是合法的、信息丰富的警告。在这两种情况下,调用具有错误原型的函数都是非法的。某些 ABI 要求函数清理堆栈,在这种情况下,将参数传递给不接受任何参数的函数,就像不将参数传递给需要参数的函数一样,肯定会破坏堆栈。

C99 6.3.2.3 段8:

指向一种类型的函数的指针可以转换为指向
另一种类型的函数然后再返回;结果应比较
等于原来的指针。如果使用转换后的指针来调用
其类型与所指向的类型不兼容的函数,
行为未定义

The difference between the two cases is explained like this: if you pass a parameter to a function that accepts none, you are just consuming some memory on the stack. If you don't pass any parameter to a function that accepts a few, the latter is going to read random data from the stack.

Update: changed to community wiki to add these corrections from Pascal Cuoq:

Casts of function pointer in both directions are legal, informative warnings from the compiler notwithstanding. Calling a function with the wrong prototype is illegal in both cases. Some ABIs mandate that the function clean up the stack, in which case passing parameters to functions that accept none corrupt the stack as surely as not passing parameters to functions that expect them.

C99 6.3.2.3 par. 8:

A pointer to a function of one type may be converted to a pointer to a
function of another type and back again; the result shall compare
equal to the original pointer. If a converted pointer is used to call
a function whose type is not compatible with the pointed-to type, the
behavior is undefined

汹涌人海 2024-12-09 15:48:40

这是您收到的警告:

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

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

This is the warning you get:

warning: initialization from incompatible pointer type

You are passing void which means that will require a cast. You should use the right types.

烂人 2024-12-09 15:48:40

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

IIRC C compiler has certain assumptions which can cause very odd bugs because you're not telling it how much stack space it needs whenever that function is called. Especially since the definitions don't match this might allow someone to inadvertently read your function pointer declaration and assume no parameters and have the function return garbage. If you really want to take variable numbers of parameters use my_func(...) and varargs.

浅笑依然 2024-12-09 15:48:40

警告就是警告。诚实的。

在这种情况下,编译器知道您的函数指针类型不正确,并且它会公然地告诉您这一点。如果您尝试传递多个参数而不是 3 个,则会发出错误。

A warning is just that, a warning. Honest.

In that case, the compiler knows you have an incorrect function pointer type and it blatantly tells you that. If you try to pass a number of parameters different then 3, then it will be issued an error.

因为看清所以看轻 2024-12-09 15:48:40

我认为问题与参数的转换有关,因为 char 不是 32 位。请注意,如果将 char 更改为 int,则效果很好。它与变量的自动提升有关。

比较两者:

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

gcc

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

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

I think that the problem is related to the casting of the parameters, because char is not 32 bits. Note that if you change the char to int this works fine. It is related to automatic promotion of variables.

Compare the two:

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

and

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

gcc gives you warning for the second, but not for the first

乞讨 2024-12-09 15:48:40

在 C 中,空参数列表意味着该函数不带任何参数。我相信您将空参数列表与可变参数混淆了。

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

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

In C an empty parameter list means that the function does not take any parameters. I believe you are confusing an empty parameter list with varargs.

Changing your first example to include the parameters will remove the warning.

int func(double a, int b, char c)
{
    return 0;
}
int main()
{
    int(*myPointer)(double, int, char) = func;
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文