類型轉換

一 c中數據類型的隱式轉換


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

2、算數運算的隱式轉換
    算數運算中,首先有如下類型轉換規則:
       1、字符必須先轉換爲整數(C語言規定字符類型數據和整型數據之間可以通用) 。
       2、short型轉換爲int型(同屬於整型) 。
       3、float型數據在運算時一律轉換爲雙精度(double)型,以提高運算精度(同屬於實型) 。
    其次,有下面的規則。
    當不同類型的數據進行操作時,應當首先將其轉換成相同的數據類型,然後進行操作,轉換規則是由低級向高級轉換。轉換規則如下圖所示: 
 

    上圖的簡化圖如下所示:
 

3、算數運算示例
    執行:x = 100 + 'a' + 1.5 * u + f / 'b' - s * 3.1415926
    其中,u 爲unsigned 型,f 爲float 型,s 爲short 型,x 爲float 型。式中右面表達式按如下步驟處理:
       1、首先將'a' 、'b' 和s 換成int ,將1.5 和f 轉換爲double 型。 
       2、 計算100+'a' ,因'a' 已轉換爲int 型,於是此運算結果爲197 。 
       3、 計算1.5*u ,由於1.5 已轉換爲double ,u 是unsigned 型,於是首先u 轉換爲double ,然後進行運算,運算結果爲double 。 
       4、 計算197+1.5 * u ,先將197 轉換爲double (如197.00 …00 ),其結果爲double 
       5、 計算f/ 'b' ,f 已轉換爲double ,'b' 已轉換爲int ,於是先將'b' 再轉換爲double ,其結果爲double 。 
       6、 計算(197+1.5 * u )+f / 'b' ,者均爲double ,於是結果也爲double 。 
       7、 計算s * 3.1415926 ,先將s 由int 轉換爲double ,然後進行運算,其結果爲double 。 
       8、 最後與前面得的結果相減,結果爲double 。 
       9、 最後將表達式的結果轉換爲float 並賦給x 。


********

 

二 c中數據類型的強制轉換

 

       強制類型轉換是通過類型轉換運算來實現的。其一般形式爲: (類型說明符) (表達式)其功能是把表達式的運算結果強制轉換成類型說明符所表示的類型。

       例如: (float) a 把a轉換爲實型(int)(x+y) 把x+y的結果轉換爲整型在使用強制轉換時應注意以下問題:
      1.類型說明符和表達式都必須加括號(單個變量可以不加括號),如把(int)(x+y)寫成(int)x+y則成了把x轉換成int型之後再與y相加了。
      2.無論是強制轉換或是自動轉換,都只是爲了本次運算的需要而對變量的數據長度進行的臨時性轉換,而不改變數據說明時對該變量定義的類型 

 

例1 :
main()
{
float f=5.75;
printf("(int)f=%d,f=%f/n",(int)f,f);
}


結果 :

(int)f = 5 ,f = 5.750000 

將float f強制轉換成int f float f=5.75; printf("(int)f=%d,f=%f/n",(int)f,f);

 例表明,f雖強制轉爲int型,但只在運算中起作用, 是臨時的,而f本身的類型並不改變。因此,(int)f的值爲 5(刪去了小數)而f的值仍爲5.75 

 

 

例2 :

     比如我們可以(int)'A',這樣轉換後的結果爲A的ASCII碼數值,因爲那塊內存本來就存的那個數,只是換個形式使用而已。 知道上面的原則,我們可以對任何數據類型進行轉換,但是轉換的結果可能不是你想像的結果,舉例(int)'9'的結果爲多少?不是9而是0x39(’9‘的ASCII碼值)。

     來個高 深點的printf("%d",'12') ; 的輸出是什麼?正確答案是12849,因爲printf("%d",'12'),打印的是存儲12的內存地址上的內容,即存儲真實的ASCII碼值,12的高位數存儲在低位地址,即1存儲在低位,低位存儲在高位地址 (大端),0x32就是2的ASCII碼,0x31就是1的 ASCII碼,所以是0x3231,轉換成10進制就是12849!  在我計算機上用Linux打印出來是12594,0x3132轉換成十進制數就是12594!(與機器的大小端有關係,就像char a = '12';打印輸出a時候,在我的Linux是2。--X86是小端)。

 

 

● 字符型變量的值實質上是一個8位的整數值,因此取值範圍一般是-128~127,char型變量也可以加修飾符unsigned,則unsigned char 型變量的取值範圍是0~255(有些機器把char型當做unsighed char型對待, 取值範圍總是0~255)。
● 如果一個運算符兩邊的運算數類型不同,先要將其轉換爲相同的類型,即較低類型轉換爲較高類型,然後再參加運算,轉換規則如下圖所示。
double ←── float 高

long

unsigned

int ←── char,short 低
● 圖中橫向箭頭表示必須的轉換,如兩個float型數參加運算,雖然它們類型相同,但仍要先轉成double型再進行運算,結果亦爲double型。 縱向箭頭表示當運算符兩邊的運算數爲不同類型時的轉換,如一個long 型數據與一個int型數據一起運算,需要先將int型數據轉換爲long型, 然後兩者再進行運算,結果爲long型。所有這些轉換都是由系統自動進行的, 使用時你只需從中瞭解結果的類型即可。這些轉換可以說是自動的,但然,C語言也提供了以顯式的形式強制轉換類型的機制。
●  較低類型的數據轉換爲較高類型時,一般只是形式上有所改變, 而不影響數據的實質內容, 而較高類型的數據轉換爲較低類型時則可能有些數據丟失 

 

 

 

賦值中的類型轉換


當賦值運算符兩邊的運算對象類型不同時,將要發生類型轉換, 轉換的規則是:把賦值運算符右側表達式的類型轉換爲左側變量的類型。 具體的轉換如下:
(1) 浮點型與整型 
● 將浮點數(單雙精度)轉換爲整數時,將捨棄浮點數的小數部分, 只保留整數部分。
將整型值賦給浮點型變量,數值不變,只將形式改爲浮點形式, 即小數點後帶若干個0。注意:賦值時的類型轉換實際上是強制的。
(2) 單、雙精度浮點型 
● 由於C語言中的浮點值總是用雙精度表示的,所以float 型數據只是在尾部加0延長爲doub1e型數據參加運算,然後直接賦值。doub1e型數據轉換爲float型時,通過截尾數來實現,截斷前要進行四捨五入操作。 
(3) char型與int型 
● int型數值賦給char型變量時,只保留其最低8位,高位部分捨棄。 
● chr型數值賦給int型變量時, 一些編譯程序不管其值大小都作正數處理,而另一些編譯程序在轉換時,若char型數據值大於127,就作爲負數處理。對於使用者來講,如果原來char型 數據取正值,轉換後仍爲正值;如果原來char型值可正可負,則轉換後也仍然保持原值, 只是數據的內部表示形式有所不同。 
(4) int型與1ong型 
● long型數據賦給int型變量時,將低16位值送給int型變量,而將高16 位截斷捨棄。(這裏假定int型佔兩個字節)。 
將int型數據送給long型變量時,其外部值保持不變,而內部形式有所改變。 
(5) 無符號整數 
● 將一個unsigned型數據賦給一個佔據同樣長度存儲單元的整型變量時(如:unsigned→int、unsigned long→long,unsigned short→short) ,原值照賦,內部的存儲方式不變,但外部值卻可能改變。
● 將一個非unsigned整型數據賦給長度相同的unsigned型變量時, 內部存儲形式不變,但外部表示時總是無符號的。 
/*例:賦值運算符舉例 */
main()
{ unsigned a,b;
int i,j;
a=65535;
i=-1;
j=a;
b=i;
printf("(unsigned)%u→(int)%d/n",a,j);
printf("(int)%d→(unsigned)%u/n",i,b);
}
運行結果爲:
(unsigned)65535→(int)-1
(int)-1→(unsigned)65535

● 計示負值,爲0時表示正值。如果一個無符號數的值小於32768則最高位爲0,賦給 int型變量
 算機中數據用補碼錶示,int型量最高位是符號位,爲1時表 後、得到正值。如果無符號數大於等於32768,則最高位爲1, 賦給整型變量後就得到一個負整數值。反之,當一個負整數賦給unsigned 型變量時,得到的無符號值是一個大於32768的值。 
● C語言這種賦值時的類型轉換形式可能會使人感到不精密和不嚴格,因爲不管表達式的值怎樣,系統都自動將其轉爲賦值運算符左部變量的類型。 
● 而轉變後數據可能有所不同,在不加註意時就可能帶來錯誤。 這確實是個缺點,也遭到許多人們批評。但不應忘記的是:c面言最初是爲了替代彙編語言而設計的,所以類型變換比較隨意。當然, 用強制類型轉換是一個好習慣,這樣,至少從程序上可以看出想幹什麼。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章