为什么下列程序进行的是无符号乘法?

26 天前
 rookiemaster
unsigned int x1 = 0xaeb1c2aa;
unsigned int x2 = 0xaeb1c2aa;

long long r_whole = (signed long long)x1 * (signed long long)x2;

printf("r_whole = %lld\n",r_whole);

输出的结果是无符号乘法的结果:

r_whole = 8590088583138384100

而下面的程序

unsigned int x1 = 0xaeb1c2aa;
unsigned int x2 = 0xaeb1c2aa;

int xx1 = x1;
int xx2 = x2;

long long r_whole = (signed long long)xx1 * (signed long long)xx2;

printf("r_whole = %lld\n",r_whole);

输出的事有符号乘法的结果:

r_whole = 1860719719092984036

第一段程序里我不是对 x1 进行强制类型转换了吗

963 次点击
所在节点    C
6 条回复
chingyat
26 天前
因为后者 xx1 和 xx2 是负数.
Hsinyao
26 天前
不要纠结这些语法,建议 objdump 看汇编
lindt99cocoa
26 天前
无符号数做零扩展,有符号数做符号扩展
ysc3839
26 天前
因为 1 没符号,转成有符号类型时也不带符号,2 有符号,转成有符号类型时就会带符号
cnbatch
26 天前
写成这样就容易懂了:

uint32_t x1 = 0xaeb1c2aa; // 2930885290
uint32_t x2 = 0xaeb1c2aa;

int64_t var1 = x1;
int64_t var2 = x2;

long long r_whole = var1 * var2;

x1 和 x2 强制转换成 signed long long 的时候,实际上就相当于 int64_t var1 = x1;
有符号 long long 能够容纳的范围足够大,大到可以完整“吞下”整个 0xaeb1c2aa
iceheart
25 天前
第二个数值溢出,转成 int 型变成负数了
int 扩展成 long long ,高位按符号位扩展,所以仍是负数。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1034018

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX