我在将代码编译为'C'和编译为'C++'时得到了以下差异
struct A {
int x;
int y;
};
struct A get() {
return {0};
}
在编译为'C++'时一切正常。 但是,在编译为'C'时,我遇到了:
错误:预期表达式
我可以通过执行以下操作来解决:
return (struct A){0};
然而,我想知道这个差异来自哪里。有人能指出语言参考文献中这个差异是从哪里来的吗?
我在将代码编译为'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)),该条款规定:
(...) 带有花括号初始化列表的返回语句通过从指定的初始化器列表进行复制列表初始化来初始化要从函数返回的对象或引用。 [ 例如:
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}; }
使用了C99特性中的“复合字面量”,这在C++中并不存在(尽管一些C++编译器,尤其是gcc,以语言扩展的形式提供此特性;gcc会用-pedantic警告)。该语义在C99标准的第6.5.2.5节中有详细描述;关键引文如下:
4、由带括号的类型名后跟花括号括起来的初始化列表组成的后缀表达式是一个复合字面量。它提供了一个未命名对象,其值由初始化列表给出。(脚注80)
80)请注意,这与强制转换表达式不同。例如,强制转换仅指定对标量类型或
void
的转换,强制转换表达式的结果不是左值。因此,在这种情况下,
(struct A){0}
是一个未命名的对象,并被复制到返回值中返回。(注意现代编译器将省略此副本,因此您无需担心运行时开销)所以,这就是所有的信息了。为什么这些特性以各自编程语言中的方式存在可能会成为一场迷人的讨论,但我担心任何外部标准化委员会的人都难以给出权威答案。这两个特性是在C和C++分道扬镳之后引入的,它们并不是并行开发的(也没有意义这样做)。即使是小事,分歧也是不可避免的。
(struct A){0}
实际上返回的是什么?据我所知,return
语句应该是 (struct A){0, 0}
。 - haccksreturn
语句是(struct A){.x = 0}
,那就是这种情况。而且这个引用与数组初始化有关。我问这个问题是因为我不确定结构体,或者可能是我记忆中遗漏了这一点。 - haccks