gcc x86上的int64_t范围限制是多少?

d6kp6zgx  于 2022-11-13  发布在  其他
关注(0)|答案(3)|浏览(397)

在x86上测试一些整数乘法。

int32_t a = 2097152;
int64_t b = a * a;

为什么上面的b的计算结果为零?

f87krz0w

f87krz0w1#

x86上的int64_t范围限制是多少?
C11标准7.20.2.1说[-2^63; 2^63-1]等效于[-9223372036854775808;9223372036854775807],你可以通过打印INT64_MAXINT64_MIN来获得它。
为什么上述b的值为零?
因为只有在乘法运算完成后,提升才会发生。a*a的结果是int32_t类型,当溢出一个有符号整数时,就会调用未定义的行为。实际上,你所做的是:

int32_t a = 2097152;
int32_t tmp = a * a;
int64_t b = tmp;

您可以通过以下方式获得所需的结果:

int32_t a = 2097152;
int64_t b = ((int64_t) a) * a;

外括号不是必需的,但重要的是要理解,我不是在谈论(int64_t)(a*a),因为它不会产生正确的结果。

ycggw6v2

ycggw6v22#

int64_t限制在您的示例中是无关紧要的,因为b类型仅在计算a * a表达式 * 之后 * 才起作用,并且损害已经造成。
当执行算术时,执行“普通算术转换”,即值被转换为至少为int的公共类型;在本例中,int32_t很可能已经是int了,所以这两个值保持不变,执行32位乘法。这会溢出int32_t的范围,结果如图所示(请注意,有符号溢出实际上是未定义的行为)。
要使其按预期运行,必须首先将至少一个操作数强制转换为int64_t,以便乘法以64位算术方式执行。

int64_t b = ((int64_t)a) * a;
gpnt7bae

gpnt7bae3#

因为您将两个32位值相乘,得到的结果为32位。
所以实际上你会得到(a * a) % 2^32
因为
2097152 * 2097152 = 4398046511104 = 0x40000000000
得到结果的0x00000000部分。
如果你想做一个正确的64位乘法,你必须转换一个参数

int64_t b = (int64_t)a * a;

相关问题