C語言中 有符號數、無符號數、整數溢出 (轉)
- #include<stdio.h>
- void main()
- {
- int l=-1;
- unsigned int c=135;
- printf("%u\n",l+c);
- }
這個的結果134,而不是我之前認為的很大的正數,實際上需要註意的是-1(0xffffffff)被提升為unsigned int後是一個差1就溢出的unsigned int,所以相加後結果是134。但是如果l=-10000,那麽結果就真是一個很大的正數了,因為不涉及溢出了。
C語言中存在兩種整數算術運算,有符號型和無符號型。無符號數運算:所有無符號數運算都是以2的n次方為模,(n是結果中的位數)。所以它不存在運算時的沒有那種所謂的“溢出”,當它超過範圍時,從零開始重新計數!當一個無符號數和有符號數計算的時候,有符號數會自動轉化為無符號數參與運算!有符號數運算:
是可能發生“溢出”的,而且“溢出”的結果不固定。
關於無符號數減去無符號數的用法錯誤:
if ( i - j >=0) 假如i,j為無符號數,這樣寫可能會引發錯誤,即當i小於j的時候,這個式子仍然成立,因為無符號數始終是大於等於零的。例: if ( strlen( a ) >= 10) 與 if (strlen ( b ) -10 >= 0) 這兩條語句是不相等的 ,因為strlen函數返回的是無符號數類型。
2015年3月8日追加一點:今天看這個地方有些不明白在網上搜了一下資料發現,無符號數相減,如果被減數小於減數,那麽結果會是一個非常大的無符號數,而不是一個想象中的有符號數。所以對於無符號數相減之前需要進行判斷,最好做比較的時候使用 if ( strlen( a ) >= 10) 這種方式,而不要使用if
(strlen ( b ) -10 >= 0) 這種方式。因為無符號數進行計算的結果還是無符號數;另外無符號數和有符號數計算時,有符號數會被強制轉提升無符號數。
例如以下這個例子很有意思:
[cpp] view plain copy print?
- #include<stdio.h>
- int main()
- {
- unsigned int a=6;
- int b=-20;
- printf("%d\n",(a+b)>0);
- }
這個小例子可以機器試一下。另外還有幾道題不錯我也附在最後。
需要註意一點,我在進行程序編寫的時候發現一個小問題:
那麽unsigned char與signed int相減呢?
[cpp] view plain copy print?- #include<stdio.h>
- void main()
- {
- unsigned char a;
- int b;
- a=0;
- b=2;
- printf("X=%d\n",(a-b)>0);
- }
ANSI C規定在無符號整數和有符號整數之間進行強制類型轉換時,位模式不應該改變。類型轉換並未改變對象的位模式,改變的是位模式的解釋方式。
有符號數轉換為無符號數時,負數轉換為大的正數(可以理解為原值加上2的n次方),而正數保持不變。
無符號數轉換為有符號數時,對於小的數將保持原值,對於大的數則轉換為負數(可以理解為原值減去2的n次方)。
今晚在看C的時候突然想到如果把大於unsigned int的範圍的數據賦予 該類型變量,printf出來會是什麽樣。
[cpp] view plain copy print?
- void main()
- {
- unsigned int a;
- a=7000000000;
- printf("a=%d\n",a);
- printf("a=%u\n",a):
- }
這兩個結果是完全不一樣的。
幾個小例子:
題目一:
int a = -1;
unsigned int b = 1;
printf("%d", a > b);
結果輸出:1
因為無符號數與有符號數比較時,要將有符號數轉化為無符號數,再來比較。a轉化為無符號數後就是0xFFFFFFFF,肯定大於b
題目二:
char a = -1;
unsigned char b = 1;
printf("%d", a > b);
結果輸出:0
奇怪了,怎麽會這樣?這是因為兩者被提升為int了,a提升為int就表示-1,b提升為int 就是1,前者小於後者。註意了這裏不是像題目一裏一樣簡單的把char轉化為unsigned char了
題目三:
int a = -1;
unsigned char b = -1;
printf("%d\n", a < b);
結果輸出是:1
原因在於要把b提升為int就是255當然大於-1了,unsigned char 先提升為int,送入int的低八位中,高位全部補零。
題目四:
char a = -1;
unsigned int b = -1;
printf("%d\n", a == b);
結果輸出:1
原因是char類型被擴展為unsigned int後與b相等,同為0xFFFFFFFF
小於int的提升到int,int之後都是從signed -> unsigned
對於浮點數來說,浮點數(float,double)實際上都是有符號數,unsigned 和signed前綴不能加在float和double之上,當然就不存在有符號數根無符號數之間轉化的問題了。
一定要記住如果需要使用有符號數時不要忘記強制轉換
C語言中 有符號數、無符號數、整數溢出 (轉)