c - C 是否保证 32 位整数运算?
问题描述
在 C 中,假设int
是 32 位,
uint64_t x = 1000000u * 1000000u;
这通常通过将 32 位结果的数字相乘,丢弃溢出位,然后用零扩展分配给x
.
语言是否保证这一点,或者编译器是否可以选择以 64 位执行所有操作,从而给出数学上准确的结果?
(我知道语言标准int
首先允许使用 64 位。我说的int
是 32 位的情况。)
解决方案
uint64_t x = 1000000u * 1000000u;
您声明的假设是int
32 位。为了 100% 清楚,我们需要假设UINT_MAX
2 32 -1 或4294967295
。(标准要求unsigned int
范围至少为 0 到 65535,这意味着大小至少为 16 位——但它可以有填充位。)几乎可以肯定是同一件事(我不知道任何 C 实现有填充位),但是如果我们想问标准保证什么,我们应该明确。
给定这个假设,常数1000000u
是类型unsigned int
,乘法的结果3567587328u
也是类型unsigned int
。该值被转换为uint64_t
(不丢失信息)并存储在x
.
uint64_t
保证完全是 64 位宽,没有填充位。没有满足这些条件的类型的实现将不会定义uint64_t
,因此上述内容无法编译。(当然,我假设这指的uint64_t
是标准<stdint.h>
或<inttypes.h>
标题中定义的。)
算术表达式的一般规则是表达式的类型取决于其操作数的类型,而不是其操作数的值或它出现的上下文。如果我们放弃关于 的上限的假设unsigned int
,则常数1000000u
可以是unsigned int
或类型unsigned long
,无论哪种类型大到足以容纳它——但乘积的值与常数的类型相同,即使这会导致溢出环绕。(严格来说,无符号操作不会溢出。)