从C中的函数返回{0}?

时间:2015-01-11 12:27:07

标签: c++ c compiler-errors type-conversion

我在编译与C' C'之间存在以下差异。与编译为' C ++'

struct A {
  int x;
  int y;
};

struct A get() {
  return {0};      
}

编译为' C ++'一切顺利。 但是,当编译为' C&#39 ;;我得到了:

错误:预期表达

我可以通过这样做来解决:

return (struct A){0};      

然而,我想知道差异来自哪里。语言参考中的任何一点都可以指出这种差异来自何处?

1 个答案:

答案 0 :(得分:24)

两者使用完全不同的机制,其中一种是C ++ 11特定的,另一种是C99特定的。

第一位,

struct A get() {
  return {0};
}

取决于C ++ 11中的[stmt.return](6.6.3(2)),其中说

  

(...)带有 braced-init-list 的return语句通过copy-list-initialization从指定的初始化列表初始化要从函数返回的对象或引用。 [示例:

std::pair<std::string,int> f(const char *p, int x) {
  return {p,x};
}
     

- 结束示例]

C(在C ++ 11之前的C ++中)不存在这段经文,所以C编译器无法处理它。

另一方面,

struct A get() {
  return (struct A){0};
}

使用名为&#34;复合文字&#34;的C99功能。在C ++中不存在(虽然一些C ++编译器,特别是gcc,将它作为语言扩展提供; gcc用-pedantic警告它)。语义在C99标准的6.5.2.5节中有详细描述;钱报价是

  

4后缀表达式由带括号的类型名称后跟括号括起的初始值设定项列表组成,是一个复合文字。它提供了一个未命名的对象,其值由初始化列表给出。 (脚注80)

     

80)请注意,这与演员表达不同。例如,强制转换仅指定转换为标量类型或void,而转换表达式的结果不是左值。

因此,在这种情况下,(struct A){0}是一个未命名的对象,它被复制到返回值并返回。 (请注意,现代编译器将忽略此副本,因此您不必担心运行时开销)

你有它,章节和经文。为什么这些特征以他们各自语言的方式存在可能被证明是一个引人入胜的讨论,但我担心各个标准化委员会以外的任何人都难以对这个问题给出权威的答案。这两个功能都是在C和C ++拆分方式之后引入的,并且它们并不是并行开发的(这样做也没有意义)。即使在小事情上,分歧也是不可避免的。