本文是小编为大家收集整理的关于这种可疑的非原型函数声明的使用是否有效?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。
问题描述
此有效C(C99)代码?
int f(); int g(int x) { if (x<0) return f(x); else return f(x,x); }
显然,如果g曾经调用否定参数,并且f不是采用单个int参数,或者如果f> f参数和f不是占用两个int参数的函数.但否则?
作为一个示例,此单独的源文件,该文件从上面调用g并提供f:
int g(); #ifdef FOO int f(int a, int b) { return a+b; } int main() { return g(1); } #else int f(int a) { return a; } int main() { return g(-1); } #endif
推荐答案
让我们以相反的方式问:为什么不是有效?.我真的找不到任何禁止上述代码的参数或规则.各自其他分支中的函数调用永远不会执行(尽管评论中的讨论表明它并不容易!).
其他推荐答案
c99(6.5.2.2函数调用,第8项)表示,如果函数定义没有原型,则不会比较参数和参数的数量和类型.
我已经看到了在野外使用功能指针中使用的(AB). void (*)()的数组同时包含void (*)(struct Client *)和void (*)(struct Client *, int parc, char *parv[])函数指针.基于数组索引,代码是否传递了额外的参数.
在这种情况下,编译器没有(合理的)方法可以预先检查参数数量,即使它具有所有相关代码.
我认为这是肮脏的代码,我修复了该特定实例.
其他推荐答案
我同意,只要C Abstract Machine永远不会评估错误的函数调用.
不过,还有另一种简单的方法可以得出有关链接器的结论:因为这是允许的:
int f(); int (*fp)() = f;
链接器必须能够在不知道其实际定义的情况下找到f()的地址.因此,必须在不知道实际定义的情况下确定其符号.
问题描述
Is this valid C (C99) code?
int f(); int g(int x) { if (x<0) return f(x); else return f(x,x); }
Obviously the program has undefined behavior if g is ever called with a negative argument and f is not a function that takes a single int argument, or if g is ever called with a non-negative argument and f is not a function that takes two int arguments. But otherwise?
Consider as an example this separate source file which calls g from the above and provides f:
int g(); #ifdef FOO int f(int a, int b) { return a+b; } int main() { return g(1); } #else int f(int a) { return a; } int main() { return g(-1); } #endif
推荐答案
Let's ask the other way around: Why would it not be valid?. I really can't find any argument or rule that forbids the above code. The function call in the respective other branch is never executed (although discussion in the comments indicate it's not so easy!).
其他推荐答案
C99 (6.5.2.2 Function calls, item 8) says the number and types of parameters and arguments "are not compared" if the function definition does not have a prototype.
I have seen this (ab)used in the wild with function pointers. An array of void (*)() contained both void (*)(struct Client *) and void (*)(struct Client *, int parc, char *parv[]) function pointers. Based on the array index, the code passed the extra parameters or not.
In this case, the compiler has no (reasonable) way to check the number of parameters in advance, even if it has all relevant code.
I think this is dirty code and I fixed that particular instance.
其他推荐答案
I would agree that it is valid so long as the incorrect function call is never evaluated by the C abstract machine.
There is another, simpler, way to come to your conclusion about the linker, though: Since this is allowed:
int f(); int (*fp)() = f;
The linker must be able to find the address of f() without knowing its actual definition. Its symbol must therefore be able to be determined without knowing the actual definition.