此有效的C(C99)代码是吗?

int f();
int g(int x)
{
    if (x<0) return f(x);
    else return f(x,x);
}

显然,该程序具有不确定的行为 g 曾经被称为消极论点,并且 f 不是一个单一的函数 int 论点,或者是否 g 被称为非负论点, 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() 不知道其实际定义。因此,必须在不知道实际定义的情况下确定其符号。

如果是 f(int x, ...) 它查看其第一个论点的迹象是知道它有多少(0或1)varargs?

它是有效的(嗯,这可能取决于您使用的标准)。你应该读一些有关的东西 召集会议.

基本上,如果 f 有一个或没有争论,我期望没有问题。
如果 f 采用两个或多个参数,可以期望那些其他参数(除第一个)具有垃圾(显然是随机的)值。

考虑此代码:

int f(int x, int y);
int g(int x)
{
   int k; //No value
   if (x<0) return f(x, k);
   else return f(x, x);
}

当然,这是一个坏主意。您应该更喜欢明确声明所有论点。

您也可以使用 int f(void); 明确宣布F没有任何争论。

请注意,C ++的功能超载可能会导致问题,但我认为这不是一个问题,因为您将问题标记为 c。另外,一些召集约定可能会引起重大问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top