如果C编译器填充结构以便将字段与其原始对齐对齐,然后初始化该结构,则填充是否初始化为零?
例如以下结构:
typedef struct foo_t_ {
int a;
char b;
int c;
char d;
} foo_t;
Run Code Online (Sandbox Code Playgroud)
在许多系统上,这个(设计不佳)的结构将具有sizeof(foo_t)16个,总共6个字节的填充,每个字符后3个字节.
如果我们初始化结构,如:
foo_t foo = { .a = 1, .b = '2' };
Run Code Online (Sandbox Code Playgroud)
然后字段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));
Run Code Online (Sandbox Code Playgroud)
我想确定hash_foo并且hash_bar是一样的.我可以通过首先使用memset()清除结构然后初始化它来保证这一点,但是使用C初始化代替它似乎更清晰.
在实践中,我的系统上的GCC也确实清除了填充,但我不知道这是否有保证.
我需要一个好的伪随机数发生器(PRNG),看起来当前的技术水平是xorshift128 + algoritm.不幸的是,我发现了2个不同的版本.维基百科上的那个:Xorshift显示为:
uint64_t s[2];
uint64_t xorshift128plus(void) {
uint64_t x = s[0];
uint64_t const y = s[1];
s[0] = y;
x ^= x << 23; // a
s[1] = x ^ y ^ (x >> 17) ^ (y >> 26); // b, c
return s[1] + y;
}
Run Code Online (Sandbox Code Playgroud)
这似乎很直接.更重要的是,编辑日志似乎显示这个代码片段是由名为"Vigna"的用户添加的,该用户可能是"Sebastiano Vigna",他是xorshift128 +论文的作者:Marsaglia的xorshift生成器的进一步组织.不幸的是,该文件中的实施略有不同:
uint64_t next(void) {
uint64_t s1 = s[0];
const uint64_t s0 = s[1];
s[0] = s0;
s1 ^= s1 << 23; // a
s[1] …Run Code Online (Sandbox Code Playgroud)