rookiemaster
V2EX  ›  C

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

  •  
  •   rookiemaster · Apr 19, 2024 · 4339 views
    This topic created in 781 days ago, the information mentioned may be changed or developed.
    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 replies    2024-04-20 14:32:11 +08:00
    chingyat
        1
    chingyat  
       Apr 19, 2024 via iPhone
    因为后者 xx1 和 xx2 是负数.
    Hsinyao
        2
    Hsinyao  
       Apr 19, 2024
    不要纠结这些语法,建议 objdump 看汇编
    lindt99cocoa
        3
    lindt99cocoa  
       Apr 19, 2024   ❤️ 1
    无符号数做零扩展,有符号数做符号扩展
    ysc3839
        4
    ysc3839  
       Apr 19, 2024 via Android
    因为 1 没符号,转成有符号类型时也不带符号,2 有符号,转成有符号类型时就会带符号
    cnbatch
        5
    cnbatch  
       Apr 19, 2024
    写成这样就容易懂了:

    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  
       Apr 20, 2024 via Android
    第二个数值溢出,转成 int 型变成负数了
    int 扩展成 long long ,高位按符号位扩展,所以仍是负数。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3591 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 44ms · UTC 04:51 · PVG 12:51 · LAX 21:51 · JFK 00:51
    ♥ Do have faith in what you're doing.