真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

c語言整型變量怎么用浮點型輸出

本篇內(nèi)容主要講解“c語言整型變量怎么用浮點型輸出”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“c語言整型變量怎么用浮點型輸出”吧!

成都一家集口碑和實力的網(wǎng)站建設(shè)服務(wù)商,擁有專業(yè)的企業(yè)建站團隊和靠譜的建站技術(shù),10余年企業(yè)及個人網(wǎng)站建設(shè)經(jīng)驗 ,為成都上1000家客戶提供網(wǎng)頁設(shè)計制作,網(wǎng)站開發(fā),企業(yè)網(wǎng)站制作建設(shè)等服務(wù),包括成都營銷型網(wǎng)站建設(shè),品牌網(wǎng)站建設(shè),同時也為不同行業(yè)的客戶提供網(wǎng)站設(shè)計制作、網(wǎng)站建設(shè)的服務(wù),包括成都電商型網(wǎng)站制作建設(shè),裝修行業(yè)網(wǎng)站制作建設(shè),傳統(tǒng)機械行業(yè)網(wǎng)站建設(shè),傳統(tǒng)農(nóng)業(yè)行業(yè)網(wǎng)站制作建設(shè)。在成都做網(wǎng)站,選網(wǎng)站制作建設(shè)服務(wù)商就選成都創(chuàng)新互聯(lián)。

關(guān)鍵詞:內(nèi)存存儲,類型強制轉(zhuǎn)換,反匯編

  1. 變量
    變量來源于數(shù)學(xué),是計算機語言中能儲存計算結(jié)果或能表示值抽象概念。在諸如C語言等高級語言中,變量的使用屏蔽了數(shù)據(jù)的底層細節(jié),使得高級語言程序員不必像匯編程序員那樣關(guān)心數(shù)據(jù)與硬件之間的關(guān)系。為了探究C語言中變量在內(nèi)存中的存儲形式,可以借助反匯編查看匯編語言以及內(nèi)存數(shù)據(jù)。

  2. 變量在內(nèi)存中的存儲形式
    在內(nèi)存中,無論哪種數(shù)據(jù)類型的數(shù)據(jù),都是以相應(yīng)長度的二進制碼存取。從內(nèi)存取數(shù)據(jù)是,如果不按照定義數(shù)據(jù)類型的方式取數(shù)據(jù),所取數(shù)據(jù)就會錯誤。

2.1   用反匯編查看變量內(nèi)存數(shù)據(jù)

(1)   實驗代碼如下。在賦值部分打點后調(diào)試,轉(zhuǎn)入反匯編。

(2)   在監(jiān)視窗口查看變量的內(nèi)存地址,并在內(nèi)存窗口中查看數(shù)據(jù)。

整形變量_4ByteData的數(shù)據(jù)在以內(nèi)存地址0x0023FA58起始的四個Byte中存放:【注意】 Intel處理器是小端機,數(shù)據(jù)高位在高地址,地位在地址。所存數(shù)據(jù):4Bytes的十六進制數(shù) 0x12345678




單精度浮點型變量fl的數(shù)據(jù)在內(nèi)存中的存儲:



雙精度浮點型變量df的數(shù)據(jù)在內(nèi)存中的存儲:



字符型變量ch的數(shù)據(jù)在內(nèi)存中存儲;

結(jié)論:

(1)   局部變量存儲在函數(shù)棧中,且該棧向低地址生長,所以先定義的局部變

量在較高內(nèi)存地址(比如_4ByteData在0x0023FA58,ch在0x0023FA33),并且局部變量之間并非緊密排布,而是由8個Byte 的cc數(shù)據(jù)隔開。變量周圍塞些CCCCCCCC,這可能是編譯器提供的一種保護機制,越界了好出斷言。通過網(wǎng)上查找資料,這是VC在Debug時給變量留出空間,用來檢查stack overflow。

用release調(diào)試,就不會有多余的cc。(但是注意這里char型變量與之前的局部變量之間仍有數(shù)據(jù),我猜測這里是應(yīng)為有變量對齊的緣故,char型變量也占了4byte,只不過多余的3byte由其他數(shù)據(jù)填充。)




(2)   通過觀察不同類型的變量在內(nèi)存中的存儲情況,可以發(fā)現(xiàn):

在32位機器,VS2010 IDE中,一個int型數(shù)據(jù)占4B,float型變量占4B,double型變量占8B,char型占1B。

2.2    IEEE754 單精度數(shù)的格式

單精度浮點數(shù)占據(jù)4個字節(jié),4個字節(jié)的分配如下:

(a)第一位為符號位,0表示正,1表示負;

(b)第2~9位為階碼,采用移碼表示;

(c)第10~32位為尾數(shù),采用原碼表示。

給定32位串,如何轉(zhuǎn)換成十進制數(shù):

假設(shè)內(nèi)存中存在32位串:00 00 00 3f,因為INTELCPU采用little endian存儲方式,所以其真實的值為:

0x 3f 00 00 00。將其寫成二進制形式:

(1)第一步,化為二進制

0 01111110 0000000 00000000 00000000

(2)第二步

該浮點數(shù)為正數(shù),階碼 01111110,移碼表示(126-127) = -1

尾數(shù) 0000000 00000000 00000000

因為在IEEE754中,單精度浮點數(shù)有規(guī)格化處理,所以其真正尾數(shù)部分為

1.0000000 00000000 00000000,其中‘.’為小數(shù)點

(3)   第三步

根據(jù)公式寫出實際數(shù)值大小

0.10000000 00000000 0000000 化為二進制:0.5

2.3    IEEE754 雙精度數(shù)的格式

長實數(shù)也稱雙精度數(shù)符號位1位,階碼11位,尾數(shù)52位

給定32位串,如何轉(zhuǎn)換成十進制數(shù):

假設(shè)內(nèi)存中存在64位串:00 00 00 0000 00 e0 3f,因為INTEL CPU采用littleendian存儲方式,所以其真實的值為:       0x 3f e0 00 00 00 00 00 00。將其寫成二進制形式:

(1)第一步

0 01111111110 0000 00000000 00000000 00000000 00000000 0000000000000000

(2)第二步

該浮點數(shù)為正數(shù),階碼 01111111110,移碼表示(1022-1023) = -1 尾數(shù) 0

因為在IEEE754中,單精度浮點數(shù)有規(guī)格化處理,所以其真正尾數(shù)部分為

1.0,其中‘.’為小數(shù)點

(3) 第三步

根據(jù)公式寫出實際數(shù)值大小

0.10 化為二進制:0.5
  1. 格式化輸出

3.1 printf函數(shù)調(diào)用的一般形式

printf函數(shù)是一個標準庫函數(shù),它的函數(shù)原型在頭文件“stdio.h”中。但作為一個特例,不要求在使用 printf 函數(shù)之前必須包含stdio.h文件。printf函數(shù)調(diào)用的一般形式為:printf(“格式控制字符串”, 輸出表列)。

其中格式控制字符串用于指定輸出格式。格式控制串可由格式字符串和非格式字符串兩種組成。格式字符串是以%開頭的字符串,在%后面跟有各種格式字符,以說明輸出數(shù)據(jù)的類型、形式、長度、小數(shù)位數(shù)等。如:

“%d”表示按十進制整型輸出;

“%ld”表示按十進制長整型輸出;

“%c”表示按字符型輸出等

非格式字符串原樣輸出,在顯示中起提示作用。輸出表列中給出了各個輸出項,要求格式字符串和各輸出項在數(shù)量和類型上應(yīng)該一一對應(yīng)。

3.2 類型不對應(yīng)下的格式輸出

_4ByteData = 0x12345678;  //Hexadecimal:0x12345678 對應(yīng)Decimal:305419896

fl = 0.5;

df = 0.5;

ch = 65;

printf("%d\n",_4ByteData);

printf("%c\n",_4ByteData);

printf("%d\n",ch);

printf("%f\n",&_4ByteData);

printf("%d\n",fl);

printf("%d\n",df);

分析:

可以看到同樣是int型變量,printf("%d\n",_4ByteData);與

printf("%c\n",_4ByteData);其結(jié)果分別為305419896(0x12345678對應(yīng)的十進制數(shù)),而后者只取了4字節(jié)數(shù)據(jù)的最低一個字節(jié)0x78,所以打印出了AISII碼0x78對應(yīng)的字符’x’。

聯(lián)系C語言中指針的用法,我做出假設(shè):格式輸出函數(shù)printf()根據(jù)類型字符%以及變量名,就可以根據(jù)數(shù)據(jù)首地址+讀取長度的方式輸出數(shù)據(jù)。

進一步發(fā)現(xiàn):

但是對字符型變量ch使用類型字符%d輸出,得到的是其ASCII碼的十進制數(shù),如果按照上述假設(shè),會輸出以ch地址起始的4B的數(shù)據(jù)(這將是一個錯誤數(shù)據(jù))。

但實驗結(jié)果是正確輸出了ch字符的ACSII碼的十進制數(shù)。

再對浮點數(shù)做實驗:

用類型字符%d輸出單精度數(shù),雙精度數(shù),結(jié)果均為0。

由上文2.1可知單精度浮點變量fl(十進制0.5)在內(nèi)存中占4B,機器碼是

0x00 00 00 3f(小端機)。現(xiàn)對整數(shù)_4ByteData賦值0x3f000000,并使用類型字符%f對該整數(shù)輸出,查看結(jié)果:

結(jié)果仍是0。這說明即使內(nèi)存中數(shù)據(jù)存儲的內(nèi)容一樣,但是使用類型字符%f對整型變量輸出,其結(jié)果仍然不是浮點數(shù)!

綜上,原假設(shè)值得懷疑!
  1. printf()函數(shù)類型不對應(yīng)下的格式輸出進一步研究

4.1用%d輸出float類型數(shù)據(jù)

float fl=0.5;如果用printf("%d",fl);輸出的是0。 但float型用%d輸出是否一定是0呢,答案肯定不都是0(如下圖)。

為什么 0.5 用%d輸出的是0?

分析如下:

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

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

 %d只輸出低32位的數(shù)據(jù),并將這些32位二進制以十進制數(shù)輸出,編譯器首先將 0.5從float類型轉(zhuǎn)換為double類型,0.5在內(nèi)存中的存放方式是0x3f000000,轉(zhuǎn)換成double類型在內(nèi)存中的數(shù)據(jù)就是這個0x3fe0000000000000,這個內(nèi)存數(shù)據(jù)可以很明顯看出低32位全是0,而%d則只能截取到低32位,所以這個以%d輸出0.5的數(shù)值當(dāng)然是 0了。如大家不相信可以用%lld 輸出看看,這個%lld就很讀到低64位數(shù)據(jù),讀出的結(jié)果就是0x3fe0000000000000,在屏幕上看到一個很大的十進制數(shù)。(這里用%llx顯示十六進制數(shù)更直觀)

如果我一定要輸出0.5在內(nèi)存中的存放方法怎么辦呢?

可以用printf("%d",*(int *)&fl);這里做了一下處理,不是直接把fl傳進來,把fl所在地址里的內(nèi)容處理了一下,不管fl是什么類型,只對地址進行操作,利用(int *)&lf,將fl所在地址中的內(nèi)容0x3f000000直接當(dāng)成 int 類型傳給printf,int 的類型數(shù)據(jù)不會再轉(zhuǎn)成double類型了,所以輸出正常,這個只是針對浮點型數(shù)據(jù)只占低32位,如果輸出64位還得用%lld格式控制輸出。

如果用printf("%d",(int)fl),輸出行不行?

這個強制類型轉(zhuǎn)換只針對fl的數(shù)據(jù)類型進行轉(zhuǎn)換,0.5轉(zhuǎn)換 int 類型是0,而上面的*(int *)&a,是對內(nèi)存中的實際存儲數(shù)據(jù)進行操作,蔽開數(shù)據(jù)類型這一層面,只將這個數(shù)據(jù)0x3f000000直接轉(zhuǎn)成int類型輸出。而(int)fl,要先看fl的類型,C語言會根據(jù)所要數(shù)據(jù)類型,對內(nèi)存存儲的數(shù)據(jù)進行改變,以便可以用int類型正確解析內(nèi)存數(shù)據(jù)。

如果用printf("%d",(float)fl),輸出什么,輸出的是0,這個只是將fl的float類型還轉(zhuǎn)成float類型,還是要自動轉(zhuǎn)成doube類型,傳給printf函數(shù)。

為什么float非要轉(zhuǎn)成double類型呢?

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

4.2 int類型%f格式輸出

如果定義了inta=0x3f000000;用printf("%f",a)輸出的結(jié)果是多少呢?

答案是0,至少我們看的屏幕上顯示的是0.000000,實際值可不是0啊,只是我們顯示的精度只能有15位小數(shù),而實際的數(shù)據(jù)可能很小很小,0.0000....000幾百個0后會有幾個有效數(shù)據(jù)。

我們分析一下:

首先C語言把a傳進printf,因為a是整型,所以不會自動轉(zhuǎn)成double型數(shù)據(jù),直接將0x3f0000000傳進printf,而%f尋的是64位內(nèi)存,也就是把0x000000003f000000這個內(nèi)存中的數(shù)據(jù)當(dāng)成浮點型輸出來,那浮點型的數(shù)據(jù)是多少呢,又是怎么存儲的呢?

64位浮點數(shù)的存放方式:

    63位                 62~52位                 51~0位

    1個符號位       11個階數(shù)                 52個尾數(shù)

    從0x000000003f000000來看:

   00000000

    1)符號位是0,表示正

    2)階數(shù)是0,用移碼表示:0-1023 = -1023,

用指數(shù)表示:1.#*2^-1023,‘#’是代表尾數(shù)。

    3)尾數(shù)就是,0x000003f000000

    4)浮點二進制表示

1.000000000000000000000011 1111 000000000000000000000000*2(-1023),2-1023次方可想而知有多小!

這就是為什么我們的int型數(shù)據(jù)用%f輸出是0.000000的原因!

如果把0.5的雙精度數(shù)對應(yīng)的十六進制數(shù)賦給long long類型變量,則可以輸出正確的小數(shù):
  1. 總結(jié):
    通過以上實驗,我驗證了原假設(shè)基本正確:
    格式輸出函數(shù)printf()根據(jù)類型字符%以及變量名,就可以根據(jù)數(shù)據(jù)首地址+讀取長度的方式輸出數(shù)據(jù)。

但是,還要注意其中的一些細節(jié):

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

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

到此,相信大家對“c語言整型變量怎么用浮點型輸出”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!


當(dāng)前題目:c語言整型變量怎么用浮點型輸出
本文鏈接:http://weahome.cn/article/gojede.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部