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

2020-12-20 還能說晚安咩

使用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語言基本數據類型short、int、long、char、float、double
    C 語言包含的數據類型如下圖所示:一、數據類型與「模子」short、int、long、char、float、
  • C 語言學習之變量、數據類型
    變量C 語言是強數據類型語言
  • C語言簡明教程(二)數據類型
    >數據類型實驗簡介從本章開始我們將要引入大量的 C 語言程序案例,把算法和語法結合起來,通過引導大家由淺入深地編寫 C 程序,讓大家掌握 C 語言。我們接下來將講述 C 語言的順序程序設計,由於 C 語言的順序程序設計並不容易獨立成章,也需要大家具有數據類型和表達式等相關的基礎知識,所以我們將順序程序設計這一大的章節分為以下幾個小節同時融入順序程序設計的相關例題。
  • C語言的數據類型簡述
    C語言數據類型分類C語言數據類型分類C語言的數據分類:1.基本類型:整型類型包含:基本整型(int)、短整型(short int)、長整型(long int)、雙長整型(long long int)、字符型(char)和布爾型(bool)。註:整型數據可在類型符號前面加修飾符:signed(有符號整數類型)和unsigned(無符號整數類型),若不指定則默認為「有符號類型」。
  • C語言知識點概要第二部分(數據類型)
    部分格式字符輸出舉例:"\n有符號整型數據格式:\n"); printf("%d,%hd,%ld,%lld\n",a,b,c,d); printf("\n有符號和無符號字符類型數據格式:\n"); { char ch='a'; unsigned cha=255; printf("%c,%c\n整數格式輸出:\n%d,%u\n",ch,cha,ch,cha); } printf("\n無符號整型數據格式
  • C要點5:float、double、long double(大小,範圍,輸入輸出符,科學計數法)
    浮點型:數學裡的小數C語言浮點型有三個類型:float、double、long double輸入輸出輸出格式符: 默認輸出
  • float和double有什麼區別?
    對編程人員來說,double 和 float 的區別是 double 精度高,有效數字 16 位,float 精度 7 位。但 double 消耗內存是 float 的兩倍,double 的運算速度比 float 慢得多,C 語言中數學函數名稱 double 和 float 不同,不要寫錯,能用單精度時不要用雙精度(以省內存,加快運算速度)。
  • 物聯網開發筆記——嵌入式開發之Linux系統中C語言數據類型
    嵌入式開發學習C語言打下基礎。本節介紹《Linux系統中C語言數據類型》。1 數據類型分類short、int、long、char、float、double 這六個關鍵字代表C 語言裡的六種基本數據類型。
  • Java 變量、表達式和數據類型詳解
    >整數類型 : byte short int long 小數類型 : float double2.在Java中,整數的默認類型是int,小數的默認類型是doubleboolean(布爾)類型:通常用於邏輯運算和程序流程控制(條件選擇/循環),該類型的值只能是true 或 false,表示真或假,false和true是boolean的常量;在Java語法中不可以使用0或非0的整數來代替false和true,注意區分於C語言,C語言是允許這樣的
  • 第2節:常量、變量與C語言的數據類型
    4.標識符在計算機高級語言中,用來對變量、符號常量名、函數、數組、類型等命名的有效字符序列統稱為標識符。C語言規定標識符只能由字母、數字、下劃線三種字符組成,且第一個字符必須為字母或下劃線。編譯系統將大寫和小寫認為是兩個不同字符,即區分大小寫。在計算機中,數據是存放在存儲單元中的,它是具體存在的。
  • 51單片機C語言學習(第四課 數據類型)
    先來簡單說說C語言的標識符和關鍵字。標識符是用來標識源程序中某個對象的名字的,這些對象可以是語句、數據類型、函數、變量、數組等等。
  • Java數據類型語法解析
    很多程式語言都依賴於特定的計算機類型和對Java數據類型屬性的具體編譯實現,比如word和integerJava數據類型的大小等。另一方面,Java的虛擬機負責定義其內置Java數據類型的各方面內容。Java數據類型詳解Java數據類型就是對內存位置的抽象表達。
  • MySQL教程之MySQL數據類型詳解
    本文寫的內容是MySQL數據類型,之前寫MySQL系列文章的時候一直忽略的一個知識點,現在想來,我們學習一門語言,無非從兩個方面入手:基本語法,有了語法,我們才可以組織邏輯數據類型,即在特定場景下選擇合適的數據類型,到底是用整型還是浮點型還是字符串,每種數據機構佔多少字節,最大值是多少。
  • java類型轉換String互轉int,double, float, BigDecimal
    轉換規則:從低位類型到高位類型自動轉換;從高位類型到低位類型需要強制類型轉換類似於 int i=1; double s=i+1; 這種低位類型轉換的這裡就不在做說明>String 轉 int ,double, float, BigDecimalString轉intString str = "123";
  • c語言數據運算超範圍要注意
    例如:unsigned long int X; double AD;AD=AD/50.0;X=AD*5000.0000/1023.00;最好先局部計算一下,X=AD*100/1023.00;1.浮點類型的不能做「模」運算。 例如:float a=1234.56; a=a%10; 這是錯誤的。
  • Java基本數據類型
    接觸每種語言的時候,都會存在數據類型的認識,有複雜的、簡單的,各種數據類型都需要在學習初期去了解,Java是強類型語言,所以Java對於數據類型的規範會相對嚴格。數據類型是語言的抽象原子概念,可以說是語言中最基本的單元定義,在Java裡面,本質上講將數據類型分為兩種:基本類型和引用數據類型。
  • C語言小白學習――數據類型的轉換及轉換規則
    1.不同類型數據間的混合運算與類型轉換: ①若參與運算量的類型不同,則先轉換成同一類型,然後進行運算②轉換按數據長度增加的方向進行,以保證精度不降低。如int型和long型運算時,先把int量轉成long型後再進行運算a、若兩種類型的字節數不同,轉換成字節數高的類型b、若兩種類型的字節數相同,且一種有符號,一種無符號,則轉換成無符號類型③所有的浮點運算都是以雙精度進行的,即使僅含float單精度量運算的表達式,也要先轉換成double型,再作運算④char型和short型參與運算時,必須先轉換成
  • MySQL資料庫中float、double、decimal三個浮點類型到底有什麼區別?
    1. float 浮點類型用於表示單精度浮點數值 2. double浮點類型用於表示雙精度浮點數值 這裡肯定有些小夥伴要問了 什麼是單精度? 什麼是雙精度 ?下面我們就來簡單了解一下吧!首先,我們知道一個bytes(字節) 佔8位 對吧!
  • Fluent UDF【4】:C語言
    例如:注釋也可以跨行實現,如:注意:在編寫UDF的過程中,不能把DEFINE宏(如DEFINE_PROFILE)放置在注釋中,否則會引起編譯錯誤2 基本數據類型Fluent UDF解釋器支持的標準C數據類型包括:int。
  • JAVA定義變量和基礎的數據類型和關鍵字,詳解!
    2)基本數據類型中數值類型的自動類型提升圖中依次表示了各數值類型的字節數和相應的取值範圍。在Java中,整數類型(byte/short/int/long)中,對於未聲明數據類型的整形,其默認類型為int型。在浮點類型(float/double)中,對於未聲明數據類型的浮點型,默認為double型。