【问题标题】:C - filling struct after initialization - compilation errorC - 初始化后填充结构 - 编译错误
【发布时间】:2014-09-23 13:37:07
【问题描述】:

我试图了解以下编译错误背后的原因(使用 gcc)。

0. struct mystruct {
1.     int x;
2.     int y;
3. };
4. 
5. int foo() {
6.     struct mystruct m = {1};    // compiles successfully
7.     m = {2,3};                  // compilation error: expected expression before ‘{’ token
8.     return m.x + m.y;
9. }

但是,如果我在第 7 行显式转换该值,则代码会编译:

5. int foo() {
6.     struct mystruct m = {1};    // compiles successfully
7.     m = (struct mystruct){2,3}; // compiles successfully
8.     return m.x + m.y;
9. }

我正在尝试了解此错误背后的原因。 第 6 行编译成功,没有引发错误 - 编译器自动计算出 m 的类型,无需显式转换。为什么它在第 7 行不做同样的事情?

谢谢

【问题讨论】:

  • 解决为什么需要:编译器应该如何在初始化之外知道{ 2, 3 } 的类型?例如可以是char [2] 以及struct { int a, b; } 等。
  • 可以像第 6 行一样使用 m 的类型。
  • 这将与整个语言的其余部分不一致。 C 没有类型推断,每个表达式都有一个类型。 { 2, 3 } 不能是表达式,因为它没有类型。允许的规则非常复杂,并且会使语言不那么强大。例如,您可以使用复合文字执行 void *bar = &(struct mystruct){ 2, 3 }; 等。
  • 我同意自动完成“最合适”的复合文字,以防程序员没有明确地编写它,需要复杂的规则。不过,这是用高级语言完成的。
  • C 的一个设计目标是保持语言最小化和简单,许多其他语言有不同的设计目标。所以也许答案只是“保持语法简单就是这样”。

标签: c gcc compilation compiler-errors c99


【解决方案1】:

原因是 C90 语法只允许复合 initializer

换句话说,= 右侧的大括号是一个初始化表达式,它不是 struct 类型的文字。

C99 添加了compound literals 使其工作。

【讨论】:

    【解决方案2】:

    在 C 中,符号 = 用于赋值和初始化。前者需要右侧的表达式,而大括号括起来的初始化列表则不是。

    在您的第二个示例中,您不是在处理强制转换,而是在处理复合文字,即 C99 加法。在语义上,它等价于

    struct mystruct tmp = {2,3}; // initialization
    m = tmp; // assignment
    

    【讨论】:

      【解决方案3】:

      您的第 7 行(第一个块)在 C99 中是无效的语法。赋值需要在其右侧有一个表达式,而{2,3} 不是一个有效的表达式。

      您的第 6 行(第一个块)是定义中的初始化。

      【讨论】:

        猜你喜欢
        • 2013-02-28
        • 1970-01-01
        • 2016-10-05
        • 2020-08-19
        • 2019-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多