C語言中 有符號數、無符號數、整數溢出

來源:互聯網
上載者:User

標籤:clip   問題:   title   class   相等   程式   比較   函數返回   完全   

[cpp] view plain copy print?
  1. #include<stdio.h>  
  2. void main()  
  3. {  
  4.  int l=-1;  
  5.  unsigned int c=135;  
  6. printf("%u\n",l+c);  
  7. }  

這個的結果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?
  1. #include<stdio.h>   
  2. int main()   
  3. {   
  4. unsigned int a=6;   
  5. int b=-20;   
  6. printf("%d\n",(a+b)>0);   
  7.   
  8. }   

這個小例子可以機器試一下。另外還有幾道題不錯我也附在最後。

需要注意一點,我在進行程式編寫的時候發現一個小問題:


那麼unsigned char與signed int相減呢?

[cpp] view plain copy print?
  1. #include<stdio.h>  
  2. void main()  
  3. {  
  4.  unsigned char a;  
  5.  int b;  
  6.  a=0;  
  7.  b=2;  
  8.  printf("X=%d\n",(a-b)>0);  
  9. }  

 

   ANSI C規定在不帶正負號的整數和有符號整數之間進行強制類型轉換時,位元模式不應該改變。類型轉換並未改變對象的位元模式,改變的是位元模式的解釋方式。

    有符號數轉換為無符號數時,負數轉換為大的正數(可以理解為原值加上2的n次方),而正數保持不變。

    無符號數轉換為有符號數時,對於小的數將保持原值,對於大的數則轉換為負數(可以理解為原值減去2的n次方)。


今晚在看C的時候突然想到如果把大於unsigned int的範圍的資料賦予 該類型變數,printf出來會是什麼樣。

 

[cpp] view plain copy print?
  1. void main()  
  2. {  
  3.   unsigned int a;  
  4.   a=7000000000;  
  5.  printf("a=%d\n",a);  
  6.  printf("a=%u\n",a):  
  7. }  

 

這兩個結果是完全不一樣的。


幾個小例子:

題目一:

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語言中 有符號數、無符號數、整數溢出 (轉)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.