在没有UB的情况下将64位值截断为32位值

时间:2013-12-16 09:53:27

标签: c c99

这个简单的代码片段是否具有C99标准的完全定义的行为?

{
  uint64_t longer = 0x122223333u;
  uint32_t shorter = longer;
  assert(shorter == 0x22223333u);
}

如果没有,那么符合标准的方法是什么(将uint64_t值的低32位放到uint32_t变量中?

3 个答案:

答案 0 :(得分:6)

C99标准草案说:

  

否则,如果新类型是无符号的,则通过重复添加或转换该值   减去一个可以在新类型中表示的最大值   直到该值在新类型的范围内。

因此,在这种情况下,64位值将通过从中重复减去0x1_0000_0000来转换,直到结果符合32位(为了可读性而添加了下划线)。

在您的情况下,经过一次这样的减法后,结果为0x22223333。似乎很清楚,可以证明这与截断相同,我真的不认为实际的减法发生了。

答案 1 :(得分:4)

无符号整数类型遵循模块化算法的规则,没有任何未定义的行为,因此赋值完全有效且正确。

除此之外,可选的类型uint32_tuint64_t实际上保证没有填充,并且分别是32或64位宽。

答案 2 :(得分:2)

无符号截断很好地定义为模2^n。这是签名截断,很棘手,定义较少。

所以是的,这是定义的,断言是真的,无论机器的字节顺序如何。