c - C 是否将结构填充初始化为零?

标签 c gcc struct initialization

如果 C 编译器填充结构以便将字段对齐到它们的 native 对齐方式,然后初始化该结构,填充是否初始化为零?

例如下面的结构:

typedef struct foo_t_ {
    int  a;
    char b;
    int  c;
    char d;
} foo_t;

在许多系统上,这个(设计不佳的)结构的 sizeof(foo_t) 为 16,总共有 6 个字节的填充,每个字符后有 3 个字节。

如果我们像这样初始化结构:

foo_t foo = { .a = 1, .b = '2' };

然后字段 foo.a 将设置为 1,foo.b 将设置为字符“2”。未指定的字段(`foo.c' 和 'foo.d')将自动设置为 0。问题是,填充的 6 个字节发生了什么?那也会自动设置为0吗?还是未定义的行为?

用例是我将计算数据结构的哈希值:

foo_t foo = { .a = 1, .b = '2' };
foo_t bar = { .a = 1, .b = '2' };
uint32_t hash_foo = calc_hash(&foo, sizeof(foo));
uint32_t hash_bar = calc_hash(&bar, sizeof(bar));

并且我想确保 hash_foohash_bar 相同。我可以通过首先使用 memset() 清除结构,然后初始化它们来保证这一点,但使用 C 初始化似乎更干净。

实际上,我系统上的 GCC 也会清除填充,但我不知道这是否能保证。

最佳答案

一般来说,根据 C11,对于任何未初始化对象章节 §6.2.6.1/6,

When a value is stored in an object of structure or union type, including in a member object, the bytes of the object representation that correspond to any padding bytes take unspecified values.

但是,如果完成了部分 初始化,在这种情况下,对于其余 成员,初始化就像具有静态或线程存储持续时间的对象一样发生,然后,引用相同的标准,章节 §6.7.9/21

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

关于具有静态存储持续时间的对象的隐式初始化,第 10 段

If an object that has static or thread storage duration is not initialized explicitly, then:

  • if it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;

因此,在您的情况下,剩余对象的填充保证为 0,但对于已收到初始化程序的成员则不然。

因此,总而言之,您不应该依赖于 0 的隐式初始化,而应使用memset()

话虽这么说,无论如何,不​​建议(要求)依赖于填充字节,如果有的话。使用确切的成员变量并根据这些值计算散列。

关于c - C 是否将结构填充初始化为零?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37642026/

相关文章:

c++ - 令人困惑的 C++ 模板

c - 由于 printf 不起作用,如何查看 char * 的内容?

gcc - 使用 GCC 编译的程序的许可证是什么?

c++ - 链接器错误 : undefined reference to `vtable of QGLViewer’

c - 从目标文件中提取一个部分以分隔 .o

c# - 避免将 `in` 与结构一起使用而不会使结构成为只读而降低性能?

c - 将成员添加到 C 风格结构和向后兼容性

c - 从已安装的 c 算法库编译测试文件时出错

ios - 在 Swift 中使用 C 文件导致链接器错误

c - 如何在单维字符指针数组中存储值