1

我正在使用 xorshift* 生成随机 64 位数字,并希望使用最重要的 32 位作为我的输出。仅仅创建一个指向最高有效位的指针并返回该值有什么不安全的吗?我知道我可以只使用位移,但我希望将该选项与该选项进行比较以提高性能。我已经对此方法进行了基本测试,它似乎在所有 g++ 优化级别下都按预期工作,但我不确定它是否是定义的行为,如果不是,它可能会随着项目的发展而导致问题。

uint64_t  seed = 0x2cf915021e8312a0;            // randomly chosen from random.org
uint32_t* seed_msb = (uint32_t*)(&seed) + 1;    // +1 to account for endianness

uint32_t xorshiftStar32(){
    seed ^= seed >> 12;
    seed ^= seed << 25;
    seed ^= seed >> 27;
    return (*seed_msb) * (uint64_t)(0x2545f4914f6cdd1d);
}

到目前为止我所做的测试只是检查每次调用 xorshiftStar32() 时,种子更新并且函数返回更新的结果。

4

2 回答 2

5

这是可能的,但有点狡猾(鉴于您正在修改函数中的种子,它将是一个寄存器值,因此通过指针访问不会那么有效)。在这种情况下,最好只使用 bitshift 来提取 32 位。

uint64_t seed = 0x2cf915021e8312a0;            // randomly chosen from random.org

uint32_t xorshiftStar32() {
    seed ^= seed >> 12;
    seed ^= seed << 25;
    seed ^= seed >> 27;
    return (seed >> 32) * (uint64_t)(0x2545f4914f6cdd1d);
}

这实际上会导致稍微好一点的 asm (请注意,我们已经切换了一个 mov,换了一个班次) https://godbolt.org/z/-49tZE

于 2020-01-08T06:34:26.647 回答
4

不,这会导致未定义的行为。根据严格的别名规则,只有当uint32_t左值引用一个uint32_t对象(或规则涵盖的类似对象)时,才能从左值中读取。

一个简单的解决方法是使用memcpy将您想要的字节传输到uint32_t变量中,或使用位掩码/移位/等。提取零件。

于 2020-01-08T06:43:18.470 回答