C 数据溢出与精度丢失

有符号 short 溢出(有符号整数溢出属于未定义行为)

c 复制代码
#include <stdio.h>
int main() {
    short num = 0x7FFF;
    printf("%hd \r\n", num);
    num = 0x8000;
    printf("%hd \r\n", num);
    return 0;
}
  1. short:2 字节 = 16bit,默认signed有符号
    ○ 范围:-2^15 ~ 2^15-1,即 -32768 ~ 32767
    ○ 0x7FFF:二进制0111 1111 1111 1111 → 32767(最大值)
    ○ 0x8000:二进制1000 0000 0000 0000 → -32768(最小值)
  2. 调试自增演示
c 复制代码
short num = 32767;
num++;   // 32767 +1,二进制进位,最高位变成1
printf("%hd", num); // 输出 -32768

● 汇编:movsx eax, word ptr num

● movsx:符号位扩展,把 16 位 short 扩展到 32 位 eax

● 最高位是 1,代表负数;最高位 0 代表正数

⚠️重点:C 标准里有符号整数溢出是 UB(未定义行为),只是在 VC/VS 编译器下会按补码回绕,不同编译器 / 优化等级结果可能不一样

无符号 unsigned int 溢出(标准定义:模 2^n 取余,行为确定)

c 复制代码
#include <stdio.h>
int main() {
    unsigned int num = 4294967295;
    printf("%u \r\n", num);
    num++;
    printf("%u \r\n", num);
    return 0;
}
  1. unsigned int:4 字节 = 32bit,无符号
    ○ 范围:0 ~2^32-1,最大值0xFFFFFFFF = 4294967295
    ○ 0xFFFFFFFF + 1 = 0x100000000
    ○ 只有 32 位存储空间,丢弃进位的最高位 1,剩余0x00000000,结果 = 0
    ✅重点:无符号整数溢出是 C 标准明确定义的,自动对2^32取模,一定会回绕
    反汇编核心片段解析
c 复制代码
mov dword ptr [num],0FFFFFFFFh  ; 给num赋值0xFFFFFFFF
mov eax,dword ptr [num]
push eax
push offset string "%u \r\n"
call _printf
add esp,8

mov eax,dword ptr [num]
add eax,1          ; eax = eax + 1
mov dword ptr [num],eax  ; 写回栈,超出32bit的进位直接丢弃

● add eax,1 加法指令本身会产生进位标志 CF,但存储到 32 位变量时,超出的进位不会保存,直接截断

对比总结表

类型 字节 溢出行为 C 标准规定
signed short 2 32767+1 → -32768 未定义行为 UB,仅 VC 下补码回绕
unsigned int 4 4294967295+1 → 0 确定,模2^32截断

补充易错点

  1. 不要依赖有符号数溢出回绕写代码,开启 O2 优化后结果可能完全改变
  2. 溢出本质:固定 bit 宽度,加法进位超出存储空间,发生截断;有符号还要额外解释最高位为符号位
  3. movsx(符号扩展)vs movzx(零扩展)
    ○ movsx:有符号类型扩展,高位补符号位
    ○ movzx:无符号类型扩展,高位补 0
相关推荐
布莱克6052 小时前
C/C++ 中变量的声明与定义:区别、联系与常见误区
c语言·开发语言·c++·声明·定义
LabVIEW开发2 小时前
LabVIEW 局部变量为何引发竞争条件?四种同步机制
开发语言·labview
benchmark_cc3 小时前
A 股、港股、美股如何建立统一的标的主数据格式?
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
Zenova EdgeOS4 小时前
Go 工业边缘错误处理实战:用 errors 构建可追溯错误链
开发语言·数据库·golang
取名真是4 小时前
Python 算法知识点从基础到进阶
开发语言·python·算法
FRing035 小时前
vue2干货总结3(computed计算属性、watch监听器)
开发语言·前端·vue.js·vue2
Fatbobman(东坡肘子)6 小时前
快速消失的硬盘容量 -- 肘子的 Swift 周报 #160
开发语言·人工智能·redis·ios·swiftui·iphone·swift
揽星河..6 小时前
【C语言】底层程序设计
c语言·开发语言
JavaPub-rodert6 小时前
从零搭建通用管理后台:ShiyuAdmin 的 Go、React 与 RBAC 实践
开发语言·react.js·golang
海的透彻7 小时前
dockerfile如何快速构建容器(java服务)
java·开发语言