我最近遇到了这个问题,但不明白为什么语言会允许 b = c; 低于并且失败 b = {3, 4}。允许后者有问题吗?
struct T {
int x;
int y;
};
int main()
{
T a = {1, 2};
T b;
b = {3, 4}; // why does this fail ?
T c = {3, 4};
b = c; // this works
return 0;
}
它失败{3, 4}
了,因为尽管它是一个有效的初始化程序,但它不是表达式(至少它不在 C 语言中;有关 C++ 的更多信息,请参见下文)。
C 中的每个表达式都有一个类型,可以通过检查表达式本身来确定。{3, 4}
可能是 type struct T
,或int[2]
(数组类型),或无数其他类型中的任何一种。
C99 添加了一个名为复合文字的新功能,它使用与初始化程序类似的语法,但允许您指定类型,创建一个表达式:
b = (struct T){3, 4};
请注意,这不是(struct T)
强制转换运算符;它是复合文字语法的一部分。
有关复合文字的更多信息,请参阅草案 C11 标准的第 6.5.2.5 节。
复合文字是由 1999 ISO C 标准 (C99) 引入的。如果您的编译器不支持 C99 或更高版本 (*cough*Microsoft*cough*),那么您将无法使用它们。
如果您使用的是 C++(别忘了,它是一种不同的语言),它不支持复合文字,但可能有替代方案。正如 Potatoswatter 在评论中指出的那样:
b = T{3, 4};
在 C++11 中有效(但在 C++ 语言的早期版本中无效)。这在 C++ 标准的第 5.2.3 节 [expr.type.conf] 中有介绍。
就此而言,这是:
b = {3, 4};
也是有效的 C++11 语法。这种形式可以在许多指定的上下文中使用,包括赋值的右侧。这在 C++ 标准的第 8.5.4 节 [dcl.init.list] 中有介绍。
C++ 标准的最新草案是 N3485。
(g++ 支持 C++ 中的 C99 风格的复合文字作为扩展。)
如果你被 C99 之前的编译器卡住了,你总是可以编写自己的初始化函数,例如:
struct T init_T(int x, int y) {
struct T result;
result.x = x;
result.y = y;
return result;
}
/* ... */
struct T obj;
/* ... */
obj = init_T(3, 4);
这是令人讨厌的额外工作量(这就是 C99 添加复合文字的原因),但它确实完成了工作。另一方面,在大多数情况下,使用初始化可能会更好:
struct T obj;
/* ... */
{
struct T tmp = { 3, 4 };
obj = tmp;
}
哪个更好可能取决于您的程序的结构。
因为您没有使用正确的 C99 或 C11“复合文字”表示法:
b = (struct T){ 3, 4 };
有关更多信息(以及其他地方),请参阅 ISO/IEC 9899:2011 中的 §6.5.2后缀运算符和 §6.5.2.5复合文字。
( type-name ) { initializer-list }
( type-name ) { initializer-list , }
因为这就是语言的定义......我认为除了“编写编译器来实现这一点变得更加困难”之外,我认为没有任何特别的原因。
b = T{3, 4}
如果您有 C++ 11 编译器,则可以这样做。