c語言數據類型轉換


數據類型及其占計算機中的字節大小。

 

 

 不同類型數據間的混合運算與類型轉換

1.自動類型轉換

        在C語言中,自動類型轉換遵循以下規則:

 

 

 

 

 

 

  ①若參與運算量的類型不同,則先轉換成同一類型,然后進行運算

  ②轉換按數據長度增加的方向進行,以保證精度不降低。如int型和long型運算時,先把int量轉成long型后再進行運算

            a、若兩種類型的字節數不同,轉換成字節數高的類型

            b、若兩種類型的字節數相同,且一種有符號,一種無符號,則轉換成無符號類型

   ③所有的浮點運算都是以雙精度進行的,即使是兩個float單精度量運算的表達式,也要先轉換成double型,再作運算.

   ④char型和short型參與運算時,必須先轉換成int型

   ⑤在賦值運算中,賦值號兩邊量的數據類型不同時,賦值號右邊量的類型將轉換為左邊量的類型。

 

2.強制類型轉換

        強制類型轉換一般格式如下:

            (類型名)(表達式)

        這種強制類型轉換操作並不改變操作數本身

首先進行一個實驗,分別定義一個signed int型數據和unsigned int型數據,然后進行大小比較:

unsigned int a = 20;signed int b = -130 ;b?還是b>a?實驗證明b>a,也就是說-130>20,為什么會出現這樣的結果呢?

這是因為在C語言操作中,如果遇到無符號數與有符號數之間的操作,編譯器會自動轉化為無符號數來進行處理,因此a=20,b=4294967166,這樣比較下去當然b>a了。

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

減法和乘法的運算結果類似。  unsigned int i=3;i * -1;問結果是多少

列子

 

 

  1.  為什么 7.5 用%d輸出的是0?分析如下:

        答:首先來了解下printf的輸出格式,int 和 long int 都是32位的(4個字節),用%d輸出;float 、double都是%f輸出,但 float 是32位的(4個字節),double 是64位的(8個字節),所以在參數傳遞的時候C語言統一將 float 類型數值傳換為 double 類型再傳入 printf 函數。如果是32位整型則輸出格式為%lld。

  • 為什么float非要轉成double類型呢?

   答:因為printf格式控制浮點型輸出只有%f,所以統一按doube類型輸出,不像整型有32位的%d或%ld,64位的有%lld,這就將32位整型和64位整型用不同的格式控制分開了,而%f則沒有,所以printf輸出的浮點數其實是統一遍歷了64位內存,如果float傳入printf沒有進行轉換,那么printf輸出高32位數據將不可預知,printf輸出結果也就不正確了,因此傳入printf的浮點數都會被編譯器隱含轉成double類型。

  • 下面來講一下  float a=7.5f ; printf("%d",f)輸出為0的情況:

   答:%d只輸出低32位的數據,並將這些32位二進制以十進制數輸出,編譯器首先將 7.5從float類型轉換為double類型,假設7.5在內存中的存放方式0x40f00000,轉換成double類型在內存中的數據就是這個0x401e000000000000,這個內存數據可以很明顯看出低32位全是0,而%d則只能截取到低32位,所以這個以%d輸出7.5的數值當然是 0了。如大家不相信可以用%lld 輸出看看,這個%lld就很讀到低64位數據,讀出的結果就是0x401e000000000000,在屏幕上看到一個很大的十進制數。

 

  • float f=7.5f;   如果用printf("%d",f);輸出的是0。 但float型用%d輸出是否一定是0 ?        答案肯定不都是0;

  • 如果我一定要輸出7.5在內存中的存放方法怎么辦呢?

     答:可以用printf("%d",*(int *)&f);這里做了一下處理,不是直接把a傳進來,把a所在地址里的內容處理了一下,不管a是什么類型,只對地址進行操作,利用(int *)&f,將a所在地址中的內容0x40f00000直接當成 int 類型傳給printf,int 的類型數據不會再轉成double類型了,所以輸出正常,這個只是針對浮點型數據只占低32位,如果輸出64位還得用%lld格式控制輸出。如果用printf("%d",(int)a),輸出行不行,這個強制類型轉換只針對a的數據類型進行轉換,7.5轉換 int 類型是7,而上面的*(int *)&f,是對內存中的實際存儲數據進行操作,蔽開數據類型這一層面,只將這個數據0x40f00000直接轉成int類型輸出。而(int)f,要先看a的類型,C語言會根據所要數據類型,對內存存儲的數據進行改變,以便可以用int類型正確解析內存數據。

  • 如果用printf("%d",(float)f),輸出什么?

  答:輸出的是0,這個只是將a的float類型還轉成float類型,還是自動轉成doube類型,傳給printf函數。

***********************int類型%f格式輸出************************************

  • 如果定義了int a=0x40f00000;用printf("%f",f)輸出的結果是多少呢?

   答案是0,至少我們看的屏幕上顯示的是0.000000,實際值可不是0啊,只是我們顯示的精度只能有15位小數,而實際的數據可能很小很小,0.0000....000幾百個0后會有幾個有效數據,我們分析一下。
   首先C語言把a傳進printf,因為a是整型,所以不會自動轉成double型數據,直接將0x40f00000傳進printf,而%f尋的是64位內存,就把0x0000000040f00000這個內存中的數據當成浮點型輸出來,那浮點型的數據是多少呢,又是怎么存儲的呢?
64位浮點數的存放方式:
        63位                 62~52位                   51~0位
       1個符號位              11個階數                 52個尾數
       從0x0000000040f00000來看
        1)符號位是0,表示正
        2)階數是0,表示-1023 + 1023 = 0,用指數表示:1.#*2^-1023,‘#’是代表尾數。
        3)尾數就是,0x0000040f00000
        4)浮點二進制表示
 2#1.0000000000000000000001000000111100000000000000000000*2^(-1023),-1023次方可想而知有多小。
    這就是為什么我們的int型數據用%f輸出是0.000000的原因。

5. 總結:

通過以上實驗,我驗證了原假設基本正確:

格式輸出函數printf()根據類型字符%以及變量名,就可以根據數據首地址+讀取長度的方式輸出數據。

但是,還要注意其中的一些細節:

(1)用%d輸出float類型數據時,在參數傳遞的時候C語言統一將 float 類型數值傳換為 double 類型再傳入 printf 函數。而%d只截取低32位數據,所以得到的數字不是相應浮點數的二進制碼。

(2)int類型%f格式輸出,%f尋的是64位內存,所以輸出的數據可能很小(比如2^-1023),那么結果是0.

 

 

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM