程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言基礎知識 >> C語言中的正負數以及數值溢出

C語言中的正負數以及數值溢出

編輯:C語言基礎知識
在數學中,數字有正負之分。在C語言中也是一樣,short、int、long 都可以帶上符號,例如:
short a = -10;  //負數
int b = +10;  //正數
long c = (-9) + (+12);  //負數和正數相加
如果不帶正負號,默認就是正數。

符號也要在內存中體現出來。符號只有正負兩種情況,用1位就足以表示,這1位就是最高位。以 int 為例,它占用32位的內存,0~30位表示數值,31 位表示正負號。如下圖所示:
在編程語言中,計數往往是從0開始,例如字符串 "abc123",我們稱第 0 個字符是 a,第 1 個字符是 b,第 5 個字符是 3。這和我們平時從 1 開始計數的習慣不一樣,大家要慢慢適應,培養編程思維。
在符號位中,用0表示正數,用1表示負數。例如 int 類型的 -10、+16 在內存中的表示如下:


如果不希望設置符號位,可以在數據類型前面加 unsigned,如下所示:
unsigned short a = 12;
unsigned int b = 1002;
unsigned long c = 9892320;
這樣,short、int、long 中就沒有符號位了,所有的位都用來表示數值。也就意味著,使用了 unsigned 只能表示正數,不能表示負數了。

如果是unsigned int,那麼可以省略 int ,只寫 unsigned,例如:
unsigned n = 100;
它等價於:
unsigned int n = 100;
輸出無符號數使用%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% 輸出,那麼也是有符號數。
a2、b2 的輸出值之所以很奇怪,與它們在內存中的存儲形式有關,我們將在《C語言整數在內存中是如何存儲的》一節詳細介紹。
最後需要說明的是:不管是否有符號,%o、%x、%X、%#o、%#x、%#X 都是以無符號形式輸出,讀者可以親自測試。

取值范圍和數據溢出

short、int、long 占用的字節數不同,所能表示的數值范圍也不同。以32位平台為例,下面是它們的取值范圍:
數據類型 所占字節數 取值范圍 short 2 -32768~32767,即 -215~(215-1) unsigned short 2 0~65535,即 0~(216-1) int 4 -2147483648~2147483647,即 -231~(231-1) unsigned int 4 0~4294967295,即0~(232-1) long 4 -2147483648~2147483647,即 -231~(231-1) unsigned long 4 0~4294967295,即0~(232-1)
當數值過大或過小時,有限的幾個字節就不能表示,就會發生溢出。發生溢出時,最高位會被截去。請看下面的例子:
#include <stdio.h>
int main()
{
    unsigned int a = 0x100000000;
    int b = 0xffffffff;
    printf("a=%u, b=%d\n", a, b);
    return 0;
}
運行結果:
a=0, b=-1

變量 a 為 int 類型,占用4個字節(32位),能表示的最大值為 0xFFFFFFFF,而 0x100000000 = 0xFFFFFFFF + 1,占用33位,已超出 a 所能表示的最大值,會發生溢出,最高位被截去,剩下的32位都是0。也就是說,在 a 被輸出前,其值已經變成了 0。

對於變量 b,每一位的值都是 1,包括符號位,以 %d 輸出時,按照推理應該是 -0x7fffffff = -2147483647,但是輸出結果卻是 -1,這是為什麼呢?我們將在《C語言整數在內存中是如何存儲的》一節解開謎底。
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved