gpt4 book ai didi

c - 为什么使用 "designated initializer"初始化 C union 会给出随机值?

转载 作者:太空宇宙 更新时间:2023-11-04 02:33:00 25 4
gpt4 key购买 nike

我有一个“错误”,我花了很长时间来追查:

typedef union {
struct {
uint8_t mode: 1;
uint8_t texture: 4;
uint8_t blend_mode: 2;
};
uint8_t key;
} RenderKey;

稍后将初始化此 union (在堆栈上):

Buffers buffers[128]; // initialized somewhere else

void Foo(int a, int b)
{
//C99 style initialization (all the other values should be 0)
RenderKey rkey = {.blend_mode = 1};

//rkey.key would sometimes be >= 128 thus would write out of array bounds
DoStuffWithBuffer(&buffers[rkey.key]);
}

这似乎表明 union 位域的最后一位不会被初始化。所以我通过添加未使用的位来修复它:

typedef union {
struct {
uint8_t mode: 1;
uint8_t texture: 4;
uint8_t blend_mode: 2;
uint8_t unused: 1;
};
uint8_t key;
} RenderKey;

这行得通,但我不明白为什么。那个随机的 1 位来自之前堆栈上的随机垃圾,但为什么 C99 样式初始化在这里不起作用?因为 union 和匿名 struct?

这发生在 Clang 3.5tcc 上,但不会发生在 gcc 4.9.2 上。

最佳答案

在 C11 中,§6.7.9 指出

The initialization shall occur in initializer list order, each initializer provided for a particular subobject overriding any previously listed initializer for the same subobject; all subobjects that are not initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.

但隐藏的填充位不是子对象,它不受约束,因为从匿名 struct 的角度来看它不存在,所以编译器没有初始化某些东西不是 struct 的成员,毕竟这并不奇怪。

一个类似的例子是有类似的东西

#include <stdio.h>

typedef struct {
unsigned char foo;
float value;
} Test;

int main(void) {
Test test = { .foo = 'a', .value = 1.2f};

printf("We expect 8 bytes: %zu\n", sizeof(Test));
printf("We expect 0: %zu\n", (void*)&test.foo - (void*)&test);
printf("We expect 4: %zu\n", (void*)&test.value - (void*)&test);

unsigned char* test_ptr = (unsigned char*) &test;

printf("value of 3rd byte: %d\n", test_ptr[2]);
}

test_ptr[2] 应该是什么? struct 的两个成员之间有 3 个字节的填充,它们不是任何子对象的一部分,初始化它们会浪费时间,因为在正常情况下您无法访问它们。

关于c - 为什么使用 "designated initializer"初始化 C union 会给出随机值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40949252/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com