2013-12-16 51 views
3

这个简单的代码片段是否具有完全定义的行为,由C99标准定义?将64位值截断为没有UB的32位值

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

如果不是,是实现这一点(把下一个uint64_t值的32位到uint32_t变量)符合标准的呢?

+1

你可以在'union'中覆盖这两种类型。 – Bathsheba

+0

@Bathsheba很确定那肯定是UB。 – tangrs

+0

真的吗?一个uint64_t和两个连续uint32_t的联合? – Bathsheba

回答

6

的C99草案标准表示:

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

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

在你的情况下,经过一次这样的减法后,结果是0x22223333。似乎很清楚,可以证明,这与截断是同一件事,我真的不认为实际的减法是有史以来的事情。

4

无符号整数类型服从模运算的规则,没有任何未定义的行为,所以赋值是完全有效和正确的。

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

2

无符号截断明确定义为模2^n。这是签名截断,这是棘手的和较少定义。

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