C語言中基本類型轉換(紅字部分需求證)

 1、隱式轉換
    C在以下四種情況下會進行隱式轉換:
       1、算術運算式中,低類型能夠轉換爲高類型。
       2、賦值表達式中,右邊表達式的值自動隱式轉換爲左邊變量的類型,並賦值給他。
       3、函數調用中參數傳遞時,系統隱式地將實參轉換爲形參的類型後,賦給形參。
       4、函數有返回值時,系統將隱式地將返回表達式類型轉換爲返回值類型,賦值給調用函數。

2、算數運算的隱式轉換
    算數運算中,首先有如下類型轉換規則:
       1、字符必須先轉換爲整數(C語言規定字符類型數據和整型數據之間可以通用) 。
       2、short型轉換爲int型(同屬於整型) 。
       3、float型數據在運算時一律轉換爲雙精度(double)型,以提高運算精度(同屬於實型) 。
    其次,有下面的規則。

    當不同類型的數據進行操作時,應當首先將其轉換成相同的數據類型,然後進行操作,轉換規則是由低級向高級轉換。轉換規則如下圖所示:





有符號數與無符號數之間運算問題
以下實驗均在virual c++6中運行通過
這個問題測試是否懂得C語言中的整數自動轉換原則,有些開發者懂得極少這些東西。當表達式中存在有符號類型和無符號類型時所有的操作數都自動轉換爲無符號類型。因此,從這個意義上講,無符號數的運算優先級要高於有符號數,這一點對於應當頻繁用到無符號數據類型的嵌入式系統來說是豐常重要的。 
首先進行一個實驗,分別定義一個signed int型數據和unsigned int型數據,然後進行大小比較:
    unsigned int a=20;
    signed int b=-130;
a>b?還是b>a?實驗證明b>a,也就是說-130>20,爲什麼會出現這樣的結果呢?
這是因爲在C語言操作中,如果遇到無符號數與有符號數之間的操作,編譯器會自動轉化爲無符號數來進行處理,因此a=20,b=4294967166,這樣比較下去當然b>a了。
再舉一個例子:
 unsigned int a=20;
 signed int b=-130;
 std::cout<<a+b<<std::endl;
結果輸出爲4294967186,同樣的道理,在運算之前,a=20,b被轉化爲4294967166,所以a+b=4294967186

減法和乘法的運算結果類似。

如果作爲signed int型數據的b=-130,b與立即數之間操作時不影響b的類型,運算結果仍然爲signed int型:
signed int b=-130;
std::cout<<b+30<<std::endl;
輸出爲-100。

而對於浮點數來說,浮點數(float,double)實際上都是有符號數,unsigned 和signed前綴不能加在float和double之上,當然就不存在有符號數根無符號數之間轉化的問題了。


注:以上運算時的變量類型轉換,都是在將運算後的結果進行的轉換:

   unsigned int a=20;
   signed int b=-130;
   std::cout<<a+b<<std::endl;
   結果輸出爲4294967186,同樣的道理,在運算之前,a=20,b被轉化爲4294967166,所以a+b=4294967186

  該例中其實先是20 + (-130) = -110後,將-110轉換成unsigned int 類型,其值剛好是4294967186。如果不是這樣子轉換的話下面這段代碼有點解釋不通。

   下面例子中當x = 7 和 y = -7傳入時,如果是在運算時轉換的話,那-7肯定會是個很大的正數,所以結果應該返回c = 1而不是 c = 2;只有是在運算後 7 -7 = 0;纔會返回c = 2;

    呵呵,這個地方有點小異議,希望高人指點


  1. #include <iostream>  
  2. /* 
  3. 當表達式中存在符號類型和無符號類型時 
  4. 所有的操作數都自動轉換爲無符號類型 
  5. */  
  6. using namespace std;  
  7. char getChar(int x,int y){  
  8.     char c;  
  9.     unsigned int a=x;  
  10.     unsigned int b=a+y;  
  11.     (a+y>10)?(c=1):(c=2);  
  12.     return c;  
  13. }  
  14. void main(){  
  15. char c1=getChar(7,4);  
  16. char c2=getChar(7,3);  
  17. char c3=getChar(7,-7);  
  18. char c4=getChar(7,-8);  
  19.   
  20. printf("c1=%d\n",c1);  
  21. printf("c2=%d\n",c2);  
  22. printf("c3=%d\n",c3);  
  23. printf("c4=%d\n",c4);  
  24. system("pause");  
  25. }  

答案: c1 = 1  c2=  2  c3= 2  c4= 1

   


這樣一個題,據說是微軟面試題:

unsigned int i=3;
cout<<i * -1;
問結果是多少。

第一反應:-3。不過結果似乎不是這樣的,寫了個程序,運行了一下,發現是:4294967293。很詭異的一個數字,怎麼也想不明白爲什麼會是這麼個奇怪的數字。但是在我發現這數的十六進制數是FFFFFFFD時,我想我已經離答案很近了...
 
這個涉及到了混合着不同數據類型的表達式中的數據類型的轉換問題。在總結轉換問題之前,先說明一下各種數據類型(只說明numeric類型的),下表來自MSDN:

對上表補充說明一下:
1)在32位機上,int型和unsigned int型都是32位的(4個字節)。
2)enum會跟據最大值來決定類型,一般來說爲int型,如果超出int型所能表示的範圍,則用比int型大的最小類型來表示(unsigned int, long 或者unsigned long)
3)關於類型的大小。一般用所能表示的數據範圍來比較類型的大小,如char型<unsigned char型<short型...在表達式中,一般都是由小的類型向大的類型轉換(強制類型轉換除外)
 
下面結合自己查的資料,加上自己不斷地舉各種情況編程,總結一下關於類型轉換(僅限於算術表達式中關於整數類型的轉換)的一些問題(如有缺漏,歡迎補充,感激不盡)
1、所有比int型小的數據類型(包括char,signed char,unsigned char,short,signed short,unsigned short)轉換爲int型。如果轉換後的數據會超出int型所能表示的範圍的話,則轉換爲unsigned int型;
2、bool型轉化爲int型時,false轉化爲0,true轉換爲1;反過來所有的整數類型轉化爲bool時,0轉化爲false,其它非零值都轉爲true;
3、如果表達式中混有unsigned short和int型時,如果int型數據可以表示所有的unsigned short型的話,則將unsigned short類型的數據轉換爲int型,否則,unsigned short類型及int型都轉換爲unsigned int類型。舉個例子,在32位機上,int是32位,範圍–2,147,483,648 to 2,147,483,647,unsigned short是16位,範圍0 to 65,535,這樣int型的足夠表示unsigned short類型的數據,因此在混有這兩者的運算中,unsigned short類型數據被轉換爲int型;
4、unsigned int 與long類型的轉換規律同3,在32位機上,unsigned int是32位,範圍0 to 4,294,967,295,long是32位,範圍–2,147,483,648 to 2,147,483,647,可見long類型不夠表示所有的unsigned int型,因此在混有unsigned int及long的表達式中,兩者都被轉換爲unsigned long;
5、如果表達式中既有int 又有unsigned int,則所有的int數據都被轉化爲unsigned int類型。
 
經過這番總結,前面提出的問題的答案應該就很明顯了吧。在表達式i*-1中,i是unsigned int型,-1是int型(常量整數的類型同enum),按第5條可以知道-1必須轉換爲unsigned int型,即0xffffffff,十進制的4294967295,然後
再與i相乘,即4294967295*3,如果不考慮溢出的話,結果是12884901885,十六進制0x2FFFFFFFD,由於unsigned int只能表示32位,因此結果是0xfffffffd,即4294967293。


參考:

http://blog.csdn.net/miaouu/article/details/5213042

http://blog.csdn.net/ysuncn/article/details/1787189

http://blog.sina.com.cn/s/blog_590be5290100htvu.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章