首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> C 語言基礎

C語言有符號與無符號數、數值溢出邊界分析

     編輯:C 語言基礎

符號位與 signed / unsigned

默認 short、int、long 帶符號位(最高位):0 表正,1 表負。

short a = -10;
int b = +10;      // 可省略 +
long c = (-9) + (+12);

若不需負數,加 unsigned 移除符號位,所有位存數值,**範圍翻倍但僅能表示非負數**:

unsigned short a = 12;
unsigned int b = 1002;
unsigned long c = 9892320;

unsigned int 可簡寫為 unsigned。輸出無符號數用 %u。

有符號/無符號輸出差異演示

#include <stdio.h>
#include <stdlib.h>
int main() {
    int a1 = 1234, a2 = -1234;
    unsigned int b1 = 5678, b2 = -5678;
    printf("a1=%d, a1(u)=%u\n", a1, a1);
    printf("a2=%d, a2(u)=%u\n", a2, a2);
    printf("b1=%d, b1(u)=%u\n", b1, b1);
    printf("b2=%d, b2(u)=%u\n", b2, b2);
    return 0;
}

輸出:
a1=1234, a1(u)=1234
a2=-1234, a2(u)=4294966062
b1=5678, b1(u)=5678
b2=-5678, b2(u)=4294961618

關鍵點:%u 強制按無符號解讀內存位模式;聲明為 unsigned 但用 %d 輸出,仍按有符號解讀。**存儲位模式不變,解讀方式由格式控制符決定。**

負數輸出為巨大正數,涉及補碼存儲,詳見《C語言整數在內存中是如何存儲的》。

八/十六進制輸出總是無符號

%o、%x、%X、%#o、%#x、%#X 均以無符號形式輸出。

取值範圍與溢出

32 位平台典型範圍:

類型字節範圍
short2-32768 ~ 32767
unsigned short20 ~ 65535
int4-2147483648 ~ 2147483647
unsigned int40 ~ 4294967295
long4-2147483648 ~ 2147483647
unsigned long40 ~ 4294967295

溢出演示

#include <stdio.h>
int main() {
    unsigned int a = 0x100000000; // 33 位,超出 32 位
    int b = 0xffffffff;           // 全 1 含符號位
    printf("a=%u, b=%d\n", a, b);
    return 0;
}

輸出:
a=0, b=-1

  • a:0x100000000 = 0xFFFFFFFF + 1,溢出截去最高位,剩 32 位全 0 → 0。
  • b:全 1 位模式,按有符號 %d 輸出為 -1(補碼規則),非預期的 -2147483647。詳見內存存儲專題。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved