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

sra*_*mij 15 c c++ compiler-errors type-conversion

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

struct A {
  int x;
  int y;
};

struct A get() {
  return {0};      
}
Run Code Online (Sandbox Code Playgroud)

当编译为'C++'时,一切都很顺利.但是,编译为'C'时; 我正进入(状态:

错误:预期表达式

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

return (struct A){0};      
Run Code Online (Sandbox Code Playgroud)

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

Win*_*ute 24

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

第一位,

struct A get() {
  return {0};
}
Run Code Online (Sandbox Code Playgroud)

取决于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};
}
Run Code Online (Sandbox Code Playgroud)

- 结束例子 ]

这段经文不存在于C(C++ 11之前的C++)中,因此C编译器无法处理它.

另一方面,

struct A get() {
  return (struct A){0};
}
Run Code Online (Sandbox Code Playgroud)

使用C99中不存在的称为"复合文字"的C99特性(尽管一些C++编译器,特别是gcc,将其作为语言扩展提供; gcc用-pedantic警告它).语义在C99标准的6.5.2.5节中有详细描述; 钱的报价是

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

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

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

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