这个简单的代码片段是否具有完全定义的行为,由C99标准定义?将64位值截断为没有UB的32位值
{
uint64_t longer = 0x122223333u;
uint32_t shorter = longer;
assert(shorter == 0x22223333u);
}
如果不是,是实现这一点(把下一个uint64_t
值的32位到uint32_t
变量)符合标准的呢?
这个简单的代码片段是否具有完全定义的行为,由C99标准定义?将64位值截断为没有UB的32位值
{
uint64_t longer = 0x122223333u;
uint32_t shorter = longer;
assert(shorter == 0x22223333u);
}
如果不是,是实现这一点(把下一个uint64_t
值的32位到uint32_t
变量)符合标准的呢?
的C99草案标准表示:
否则,如果新类型是无符号的,所述值是通过反复增加或 减去比可以在新类型 可以表示的最大值多一个转换直到该值在新类型的范围内。
因此,在这种情况下,64位值将通过重复减去0x1_0000_0000
进行转换,直到结果符合32位(为了便于阅读而添加下划线)。
在你的情况下,经过一次这样的减法后,结果是0x22223333
。似乎很清楚,可以证明,这与截断是同一件事,我真的不认为实际的减法是有史以来的事情。
无符号整数类型服从模运算的规则,没有任何未定义的行为,所以赋值是完全有效和正确的。
除此之外,可选的可用类型uint32_t
和uint64_t
实际上保证没有填充并且分别为32或64位宽。
无符号截断明确定义为模2^n
。这是签名截断,这是棘手的和较少定义。
所以是的,这是定义和断言是真实的,无论机器的字节顺序如何。
你可以在'union'中覆盖这两种类型。 – Bathsheba
@Bathsheba很确定那肯定是UB。 – tangrs
真的吗?一个uint64_t和两个连续uint32_t的联合? – Bathsheba