return {0} 来自 C 中的函数?

return {0} from a function in C?

编译为 'C' 与编译为 'C++'

之间存在以下差异
struct A {
  int x;
  int y;
};

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

编译为 'C++' 时一切正常。 但是,当编译为 'C';我得到:

错误:预期的表达式

我可以通过以下方式解决:

return (struct A){0};      

但是,我想知道差异是从哪里来的。语言中的任何一点都可以参考这种差异的来源吗?

两者使用完全不同的机制,一个是C++11特有的,另一个是C99特有的。

第一位,

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

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

(...) A return statement with a braced-init-list initializes the object or reference to be returned from the function by copy-list-initialization from the specified initializer list. [ Example:

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

-- end example ]

C 中不存在这段话(C++11 之前的 C++ 也不存在),因此 C 编译器无法处理它。

另一方面,

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

使用了一个名为 "compound literals" 的 C99 特性,它在 C++ 中不存在(尽管一些 C++ 编译器,特别是 gcc,将它作为语言扩展提供;gcc 会用 -pedantic 警告它)。语义在 C99 标准的第 6.5.2.5 节中有详细描述;报价是

4 A postfix expression that consists of a parenthesized type name followed by a brace-enclosed list of initializers is a compound literal. It provides an unnamed object whose value is given by the initializer list. (footnote 80)

80) Note that this differs from a cast expression. For example, a cast specifies a conversion to scalar types or void only, and the result of a cast expression is not an lvalue.

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

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