定义一个返回不兼容类型但无法访问的函数

时间:2015-11-18 14:28:16

标签: c language-lawyer c99

在阅读完C99标准后,我找不到任何禁止在下面定义函数f的部分:

struct s { double d; };

int f() {
  if (0) return (struct s){.d = 3.14};
  // There is intentionally no return statement of type int, which is valid
}

int main() {
  f();
  return 0;
}

特别是,应该定义该程序的行为,因为返回值是(a)从未达到过的,并且(b)从未使用过,即使它已达到。

尽管如此,我的大多数编译器(GCC,Clang和CompCert)都会阻止编译此程序,错误为returning 'struct s' from a function with incompatible result type 'int'。我确实设法用tcc编译它,但我不知道它是否主要是由于运气(即缺乏验证)。

有人可以确认这个程序在语法上是否有效C99,以及它的行为是否完全明确,或者说明标准禁止它的位置?

我实际上更喜欢我的编译器拒绝它,但是例如一些宏定义可以产生类似于这个的代码,所以如果这些程序有效,它们实际上是有用的。

背景

下面是我可以找到的C99标准可能相关的摘录,以及我为什么不应该禁止我的程序在语法上有效和语义定义明确的原因:

  

§6.8.6.4返回声明

     

§6.8.6.4.1带有表达式的return语句不应出现在返回类型为void的函数中。不带表达式的return语句只能出现在返回类型为void的函数中。

在我的代码中,我们有一个非void函数,返回非void,所以一切都很好。

  

§6.8.6.4.3如果执行带有表达式的return语句,则表达式的值将作为函数调用表达式的值返回给调用者。如果表达式的类型与它出现的函数的返回类型不同,则转换该值就好像通过赋值给具有函数返回类型的对象一样。

因为从不执行return语句,所以不适用。

  

§6.9.1功能定义

     

§6.9.1.12如果到达了终止函数的},并且调用者使用了函数调用的值,则行为是未定义的。

调用者不使用函数调用的结果,因此应该定义行为。

1 个答案:

答案 0 :(得分:10)

“如果表达式的类型与其出现的函数的返回类型不同,则转换该值,就好像通过赋值给具有函数返回类型的对象一样。”是一个独立的句子。它不以“如果执行带有表达式的return语句”为条件,因此甚至适用于您的代码。而且我很确定你已经知道转换好像通过赋值意味着不兼容的类型允许编译时错误。