1
我有一個「錯誤」,我花了相當長的一段追逐:爲什麼使用「指定初始值設定項」初始化C union給出隨機值?
typedef union {
struct {
uint8_t mode: 1;
uint8_t texture: 4;
uint8_t blend_mode: 2;
};
uint8_t key;
} RenderKey;
後來這個聯盟將被初始化(堆棧):
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]);
}
這似乎表明的最後一位聯合位域不會被初始化。所以,我將未使用的位固定它:
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.5
和tcc
上,但不在gcc 4.9.2
上。
我可以遵循匿名的'struct'只有7位,並且只對這些位進行初始化。這種情況令人困惑的是變量'key'在那裏,它是一個聯合。 – JBeurer
@JBeurer:你沒有通過'key'來初始化union,而是通過'struct'來完成它。所以有一個「聯盟」的事實是無關緊要的。當你選擇通過結構來初始化你的整個對象時,你將「限制」RenderKey作爲'struct'。 – Jack
換句話說,當你初始化'union'時,你選擇你要初始化它的變量。如果它是'union {uint8_t a; uint32_t b}'並且它使用'a'進行初始化(並且'b'的24個最重要的比特將最終變爲隨機的),這將不太令人困惑。 – JBeurer