V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
rookiemaster
V2EX  ›  C

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

  •  
  •   rookiemaster · 12 天前 · 829 次点击
    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 进行强制类型转换了吗

    6 条回复    2024-04-20 14:32:11 +08:00
    chingyat
        1
    chingyat  
       12 天前 via iPhone
    因为后者 xx1 和 xx2 是负数.
    Hsinyao
        2
    Hsinyao  
       12 天前
    不要纠结这些语法,建议 objdump 看汇编
    lindt99cocoa
        3
    lindt99cocoa  
       12 天前   ❤️ 1
    无符号数做零扩展,有符号数做符号扩展
    ysc3839
        4
    ysc3839  
       12 天前 via Android
    因为 1 没符号,转成有符号类型时也不带符号,2 有符号,转成有符号类型时就会带符号
    cnbatch
        5
    cnbatch  
       12 天前
    写成这样就容易懂了:

    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
        6
    iceheart  
       11 天前 via Android
    第二个数值溢出,转成 int 型变成负数了
    int 扩展成 long long ,高位按符号位扩展,所以仍是负数。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2212 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 05:27 · PVG 13:27 · LAX 22:27 · JFK 01:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.