long long res = num * num 為什麼會溢出?現象:long num = 203879; long long res = num * num; 結果錯誤(溢出),但 long long n = 203879; n * n 正確。
C 標準規定:運算在賦值前完成,運算類型由操作數決定,不受左值影響。
num 是 long(4 字節),num * num 以 long 類型計算 → 32 位溢出long long 存入 → 錯誤值被保留// 情況1:字面量直接相乘(編譯期常量折疊) movl $0xad90b171, 0x18(%esp) // 低32位 movl $0xffffffff, 0x1c(%esp) // 高32位符號擴展 → 錯誤! // 情況2:long 變量相乘 mov 0xc(%esp), %eax // 載入 num imul 0xc(%esp), %eax // 32位有符號乘法 → 溢出 sar $0x1f, %edx // 符號擴展到 edx mov %eax, 0x20(%esp) // 存低32位 mov %edx, 0x24(%esp) // 存高32位(全1) → 錯誤! // 情況3:long long 變量相乘 mov 0x14(%esp), %eax // 載入高32位(0) mov 0x10(%esp), %ecx // 載入低32位 imul 0x10(%esp), %ecx // 64位乘法指令序列 → 正確!
| 代碼 | 運算類型 | 結果 |
|---|---|---|
203879 * 203879 | int (編譯期常量折疊) | 溢出 |
long n = 203879; n * n | long (32位) | 溢出 |
long long n = 203879; n * n | long long (64位) | 正確 |
long n = 203879; 1LL * n * n | long long (提升) | 正確 |