詳解C語言數據類型:float與double

2020-12-06 還能說晚安咩

使用printf時,它們具有相同的格式說明符,但使用scanf時,它們沒有相同的格式說明符。

為什麼是這樣?因為printf的參數被提升,而scanf的參數(作為指針)卻不被提升。

這種論點提升到底是什麼?當較小尺寸的參數(特別是char,short和float)傳遞給可變參數函數(如printf之類的函數,其參數數量不固定)時,它們將轉換為較大尺寸。Char和short轉換為int,float轉換為double。

為什麼這樣 據我所知,純粹出於歷史原因。C的設計師認為這是個好主意,因為這些轉換基本上是免費的,因為所有類型的尺寸都足夠小,可以放入單個寄存器或堆棧中的單個「單元」(將內容壓入堆棧必須與某些字節邊界對齊,例如,堆棧上的每個項目都必須以4的倍數的地址開頭。同樣,顯然,這種轉換減少了傳遞參數時的錯誤。

因此,當您向printf傳遞float類型的參數時,實際上它會在轉換為printf之前就轉換為double類型。我們可以使用調試器證明這一點。我寫了下面的C代碼:

主要功能編譯成:

我在調用printf之前(在地址0x63b處)放了一個斷點。根據Linux x86_64調用約定,浮點參數在XMM寄存器中傳遞(CPU中特殊的小內存位置,可用於對多條數據並行執行同一條指令,但實際上可用於大多數事情) 。因此,我查看了第一個XMM寄存器xmm0,然後:

xmm0中的值之一,當解釋為雙精度值時,是1,恰好是我們傳遞給printf的值。同時,當將該寄存器中的值解釋為浮點數時,它們是這樣(巧合的是,我們得到1.875)。因此,轉換確實發生了。這就解釋了為什麼對於printf,我們在浮點數和雙精度參數中都使用%f -浮點數無論如何都會轉換為雙精度,因此printf不能分辨出兩者之間的區別。

同時,scanf的參數是指針,因此不受此轉換的限制。其原因是因為所有指針類型僅包含內存地址,並且所有內存地址都具有相同的大小(在我的64位計算機上為64位)。因此,當scanf在其格式字符串中獲得%f時,它將期望一個float *類型的指針,而當它獲得%lf時,將期望得到double *類型的指針。如果格式說明符和指針的類型不匹配,則會產生一些有趣的結果。

由於float的大小為4個字節,而double的大小為8個字節(至少在我的機器上),因此當我們寫入float *類型的指針所指向的位置時,我們將覆蓋4個字節的內存。同時,如果我們寫入由雙*指向的位置,則將覆蓋8個字節的內存。考慮以下代碼:

printf說明符上的.15標誌只是使printf精確度更高。由於我們使用的是雙精度值(並且正如我剛剛說的那樣,%f也適用於printf的雙精度值),因此我們實際上可以訪問具有這種精度的數字(只要它們不是太大而不能填充即可。我實際上不是對浮點表示非常了解)

編譯並運行後,結果如下:

如您所見,如果我們忽略所有類型的fuckery,則數字應該匹配,但它們甚至不相近。這是為什麼?

好吧,我們給scanf%f說明符,所以它期望一個浮點數*。但是我們傳遞了一個雙*。現在,這些指針的實際值都只是地址-scanf不知道它們之間的區別。它進行了下去,讀取我們輸入的值,並將其存儲為float 。但是浮點數僅佔用4個字節,因此scanf只會在我們可用的double變量的8個字節中寫入4個字節。在我的情況下,由於我的機器是低位字節序的,因此似乎對應於double變量的細粒度(小有效位)數字的第4個字節將被覆蓋。因此,當我們列印出double double back時,我們得到的數字幾乎與以前相同,但最低有效數字有所變化。#c語言#

相關焦點

  • 「C語言從入門到入土」必備C語言基礎筆記整理
    一、C語言1、什麼是C語言?C語言是人寫機器看的一種語言。C語言是高級語言中的低級語言。C語言貼近硬體。C語言的入門學習比較簡單。|連結:最後進行連結得到可執行程序,後綴是.exe(VS連結快捷鍵方式是 Ctrl+F5)||三、簡單說數據類型C數據類型:基本類型(數值類型(整型(短整型(Short)、整型(int)
  • 尚學堂知識整理:Java double數據類型
    double數據類型使用64位來存儲浮點數。double值也稱為雙精度浮點數。它可以表示一個最小為4.9 x 10^-324,最大為1.7 x 10^308的數字。它可以是正的或負的。所有實數被稱為double字面量。
  • java float double精度為什麼會丟失?淺談java的浮點數精度問題
    20014999 這麼小的數字在float下沒辦法表示。於是帶著這個問 題,做了一次關於float和double學習,做個簡單分享,希望有助於大家對java 浮 點數的理解。 關於 java 的 float 和 doubleJava 語言支持兩種基本的浮點類型: float 和 double 。
  • Java數據類型的「誰都看得懂」總結
    Java數據類型總結(用你敏銳的洞察力猜猜上圖可以組成什麼詞?)Java語言是一種強類型語言,所謂強類型語言就是所有變量的使用都必須嚴格符合規定,所有變量都必須先定義後使用。既然有強類型語言,就一定存在弱類型語言弱類型語言的使用就跟強類型語言恰恰相反了,他不需要先定義後使用,比如Python,JavaScript等等的計算機語言都屬於弱類型語言。
  • 自考「C語言程序設計」模擬試題十一
    「c」    B.『\\』『    C.』W『   D. 』『  14.若有代數式3ae/bc,則不正確的c語言表達式是(     )  A.a/b/c*e*3    B.3*a*e/b/c    C.3*a*e/b*c    D.a*e/c/c*3  15.在C語言中,要求運算數必須是整型的運算符是(   )  A./    B.++   C
  • 自考「C語言程序設計」模擬試題十四
    ,且n=2;while(n——);printf(「%d」,n);執行後的結果是:(     )  A.2     B.1     C.-1    D.0  15.若有以下定義和賦值double  *q,a=5.5; int  *p,i=1; double  *q,a=5.5;int *p,i=1; p=&i; q=&a; 以下對賦值語句敘述錯誤的是(
  • Python使用ctypes模塊調用DLL函數之C語言數組與numpy數組傳遞
    一般情況下,DLL函數中傳遞C語言類型的數組,在接收到Python語言中時,通常將其轉換為numpy庫裡面的數組類型,這樣做的好處是可以藉助於numpy強大的分析處理功能對數據直接作後續處理。這次通過例子演示下C語言數組到numpy數組之間是怎樣傳遞的。
  • 面試官:Java 中有幾種基本數據類型是什麼?
    (ref)這種數據類型代表一個比特的信息,但它的「大小」沒有明確的定義輸出Java 支持的數據類型包括基本數據類型和引用類型基本數據類型如下:整數值型:byte、short、int、long字符型:char浮點類型:float、double布爾型:boolean整數型:默認 int 型,小數默認是 double 型。
  • C語言基礎知識學習(一)
    c) 用戶標識符根據需要定義的標識符。一般用來給變量、函數、數組、文件等命名。用戶標誌符如果與C語言的關鍵字重名,系統報錯;若與標準庫函數重名,系統不報錯,但預定義標識符將會失去原意,代之以用戶新定義的含義。顯然如果後面用到這個函數將會報錯。
  • MSSQL數據類型-浮點數據類型 (real、float、decimal、numeric)
    浮點數據類型包括real型、float型、decimal型和numeric型。浮點數據類型用於存儲十進位小數。在SQL Server 中浮點數值的數據採用上捨入(Round up)的方式進行存儲,所謂上捨入也就是,要捨入的小數部分不論其大小,只要是一個非零的數,就要在該數字的最低有效位上加1,並進行必要的進位。由於浮點數據為近似值,所以並非數據類型範圍內的所有數據都能精確地表示。real型數據的存儲大小為4個字節,可精確到小數點後第7位數字。
  • C語言中float類型123.125在內存中存的是什麼,計算機內部是0和1
    C語言中float類型的123.125在內存中是怎樣存儲的,它是怎樣的一個二進位序列呢?下面就一起探討一下:一、運行輸出看結果編寫C語言程序如下:輸出:第一行輸出就是按照%f輸出浮點型;第二行輸出,是將f變量的地址強制轉換成int類型的指針,再取值。
  • 用C語言實現FFT算法
    nm1;i++) { if(ij) { t=xin[j]; xin[j]=xin[i]; xin[i]=t ; } k=nv2 ; while(kj) { j=j-k ; k=k/2 ; } j=j+k ; } { int le,lei,ip ; float
  • Java基礎學習:java中的基本數據類型
    2、基本信息 基本類型包括如下幾種:byte、short、int、long、float、double、boolean、char,可以通過相關方法查看範圍大小。
  • 大數據開發基礎:Java基礎數據類型
    在Java基礎入門學習階段,Java基礎數據類型無疑是基礎當中的重點,掌握基礎數據類型,對於後續去理解和掌握更深入的理論,是有緊密的關聯性的。今天的大數據開發基礎分享,我們就來講講,Java八種基礎數據類型。
  • C/C+編程筆記:C+的三大數據類型(原始、派生、抽象)
    例如:int,char,float,bool等。派生數據類型:從原始或內置數據類型派生的數據類型稱為派生數據類型。 浮點數:浮點數據類型用於存儲單精度浮點值或十進位值。用於浮點數據類型的關鍵字是float。浮點變量通常需要4個字節的存儲空間。 Double Floating Point:Double Floating Point數據類型用於存儲雙精度浮點值或十進位值。用於雙浮點數據類型的關鍵字是double。
  • C語言程序設計試題及答案
    A) int:a, b, c; B) int a; b; c;C) int a, b, c D) int a, b, c;20、C語言用( )表示邏輯「真」值。
  • C#初學者教程系列4:C 數據類型示例,int、double、string、var
    C#中的數據類型是什麼?C#語言帶有一組基本數據類型。這些數據類型用於建立在應用程式中使用的值。讓我們探索C#中可用的基本數據類型。對於每個示例,我們將只修改Program.cs文件中的main函數。本示例僅展示了基本的幾種類型,實際上它的類型不只於此。僅以本文作拋磚引玉之意。1)int類型整數數據類型用於處理數字。
  • 九碼課堂|解決方法,double類型精度丟失
    日常工作中,我們常常會遇到這麼一個問題,用double類型數據做加減運算時,例如1+20.2+300.03,理論上應該得到321.23,然而結果並不是這樣。在java中使用double進行運算時,經常容易出現精度丟失的情況,而結果總是在正確值的左右偏0.0000**1。所以double和float只適合用來做科學計算或者工程計算的場景中,而在商業計算中,我們需要使用java.math.BigDecimal對象。BigDecimal具有4個構造方法,在這裡我們只考慮兩個來進行比較。
  • C/C++編程筆記:C ++的三大數據類型(原始、派生、抽象)
    例如:int,char,float,bool等。派生數據類型:從原始或內置數據類型派生的數據類型稱為派生數據類型。 浮點數:浮點數據類型用於存儲單精度浮點值或十進位值。用於浮點數據類型的關鍵字是float。浮點變量通常需要4個字節的存儲空間。 Double Floating Point:Double Floating Point數據類型用於存儲雙精度浮點值或十進位值。用於雙浮點數據類型的關鍵字是double。
  • STM8 STM32 數據類型
    首先說一下編程過程中幾個步驟吧第一,選擇一門語言,C語言或彙編語言,嵌入式編程一般目前流行還是C,這個需要基礎與時間第二讀懂了解 MCU的寄存器各寄存器的功能,尤其是一些IO口設置,各模塊時鐘設置比如定時器,I2C,同步異步串口,PWM等等,以前的話51的話沒有這樣設置。而現在MCU基本上各模塊時鐘都分開了。