rookiemaster
V2EX  ›  C

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

  •  
  •   rookiemaster · Apr 19, 2024 · 4834 views
    This topic created in 927 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
    chingyat
    Apr 19, 2024 via iPhone
    1
    因为后者 xx1 和 xx2 是负数.
    Hsinyao
    Hsinyao
    Apr 19, 2024
    2
    不要纠结这些语法,建议 objdump 看汇编
    lindt99cocoa
    lindt99cocoa
    Apr 19, 2024❤️1
    3
    无符号数做零扩展,有符号数做符号扩展
    ysc3839
    ysc3839
    Apr 19, 2024 via Android
    4
    因为 1 没符号,转成有符号类型时也不带符号,2 有符号,转成有符号类型时就会带符号
    cnbatch
    cnbatch
    Apr 19, 2024
    5
    写成这样就容易懂了:

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