25

我最近遇到了这个问题,但不明白为什么语言会允许 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;
}
4

3 回答 3

37

它失败{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;
}

哪个更好可能取决于您的程序的结构。

于 2013-08-20T00:28:36.377 回答
6

因为您没有使用正确的 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 , }

于 2013-08-20T00:28:14.340 回答
0

因为这就是语言的定义......我认为除了“编写编译器来实现这一点变得更加困难”之外,我认为没有任何特别的原因。

b = T{3, 4}如果您有 C++ 11 编译器,则可以这样做。

于 2013-08-20T00:31:16.030 回答