【问题标题】:Partial assignment of struct in C99+C99+中结构的部分赋值
【发布时间】:2013-01-08 14:16:08
【问题描述】:

抱歉英语不好。

假设代码(C99 或更高版本):

typedef struct {
    int a, b;
} foo_t;

foo_t f = { .a = 1, .b = 2  };

f = (foo_t){ .b = 3 };

f.a 现在是什么? C标准对此有什么说法吗?

我知道对于部分初始化,标准保证所有未初始化的成员将被初始化为“适当的零”(0 用于整数,0.0 用于浮动,NULL 用于指针等.)。但最后一条语句不是初始化(据我所知),因为f 已经存在。我很困惑。

【问题讨论】:

  • 我当然不知道标准是怎么说的,但很明显,您正在分配一个新创建的(匿名)结构,该结构已部分初始化。该分配将复制所有成员,因此a 将为 0。
  • @user707650 我认为您的意思是“您正在分配 from 一个新创建的(匿名)结构,该结构已部分初始化”,对吗?并从该部分初始化的对象 分配给 f。换句话说,最后一行是创建一个临时 foo_t,其中元素 a 清零,然后将其分配给 f。 (好消息!我最初认为最后一行会简单地改变 f 中的 b 字段...)

标签: c c99 c11


【解决方案1】:

C99 标准的 6.5.2.5 复合文字 部分中的第 6 点指出:

复合文字的值是由初始化列表初始化的未命名对象的值。

未命名的foo_t 已按照您提到的相同规则进行了部分初始化。

最后一个语句是一个赋值,但复合文字是一个由初始化列表初始化的未命名对象。这意味着unnamed.a 的值为零,f.a 在赋值后为零。

【讨论】:

    【解决方案2】:

    在这个表达式中:

    f = (foo_t){ .b = 3 };
    

    (foo_t){ .b = 3 } 是复合文字,即foo_t 类型的左值,已部分初始化。它仍然是部分初始化,所以同样的规则适用:

    C11 6.7.9/21:

    如果大括号括起来的列表中的初始值设定项比那里少 是聚合的元素或成员,或 用于初始化已知大小的数组的字符串文字 是数组中的元素,聚合的其余部分应为 隐式初始化与具有静态存储的对象相同 持续时间。

    只有在复合文字被初始化后,你才能将它分配给f

    相当于这样:

    foo_t f = { .a = 1, .b = 2  };
    foo_t c = { .b = 3 };
    f = c;
    

    如果您不熟悉复合文字,GCC has good documentation for it

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-01
      • 2012-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多