1. 程式人生 > >printf輸出%f %lld問題。輸出型別和資料型別不匹配會發生什麼?

printf輸出%f %lld問題。輸出型別和資料型別不匹配會發生什麼?

——總結自《C PRIMER PLUS》

直接看三個例子:

	int a=4;
	printf("%f  %e\n",a,a);
	float b=4;
	printf("%f  %e\n",b,b);
	int n1=-1,n2=-2,n3=-3;
	printf("%lld %lld %lld\n",n1,n2,n3);
執行結果為:


可見,輸出結果並非像預期的那樣會自行轉換資料型別!

原因在於printf後邊的變數以棧的方式儲存,而%f、%lld等轉換說明符的操作方式是從棧中讀取該符號對應資料型別的位元組數,並不關心後邊對應的資料型別具體是什麼!

比如%f,要讀取8位元組,而a存到堆疊中只有4位元組,當然會出現錯誤!

再看一個例子:

	int a=4;
	double add=361263.321;
	printf("%f %d\n",a,add);

輸出結果:


原因:1091964093的十六進位制表示:


再看看double add在記憶體中的儲存:


恰好是add的後4位元組!這樣就不難理解上面的過程了。

——printf首先讀後邊的資料進棧,從右向左壓棧。然後出棧處理轉換說明符%d等

具體過程是這樣的:先把double add進棧8位元組,再把int a進棧4位元組,

這時候棧底4位元組儲存的是41 16 0c  bd;

然後輸出第一個%f,取出8位元組,取到了棧底4位元組的前邊;

然後操作%d,取出4位元組,即之前所說的41 16 0c bd

/*—————————————————————————————*/

下圖是截自原書,可以更好地理解這裡面的過程!


其中,上面是棧底,n4先入棧,n1最後入棧;

輸出先輸出第一個%ld,讀取的是float n1(4位元組);

接下來的兩個%ld讀取n2的前一半和後一半;

最後一個%ld讀取的是n3

(當然,為了保證正確的輸出,可以在輸出前轉換資料型別,這樣不會有問題!)

舉一個例子驗證這個問題


總結一下,printf語句一定要注意輸出格式和變數型別的匹配,不然會出現莫名奇妙的錯誤。

相關推薦

printf輸出%f %lld問題輸出型別資料型別匹配發生什麼?

——總結自《C PRIMER PLUS》 直接看三個例子: int a=4; printf("%f %e\n",a,a); float b=4; printf("%f %e\n",b,b); int n1=-1,n2=-2,n3=-3; printf("

型別引用型別的區別?寫出C#的樣例程式碼

值型別是在記憶體中儲存,引用型別是在記憶體中儲存一副本.你在記憶體中可以有多個某種引用物件..但是值型別始終只有一個. 最常見的值型別就是static,struct; 例如: static int a

SAP ABAP F型別D型別轉換

F型別和D型別轉換: 1.先將F型別轉換為P型別。轉換時只轉換為整數,採取四捨五入的方式。 2.將0001年01月01號作為計算基數0. 3.將轉換的P型別數字與基數進行比較得到日期值: DATA: f TYPE f VALUE '10.45',d TYPE d. WRITE

記憶體探尋1之——值型別引用型別的記憶體分配機制

String物件和值型別的記憶體分配機制:           同樣由前延伸,上上篇《由String型別分析,所產生的對引數傳遞之惑的解答》中,最後提及,如果將引用型別的按值傳遞和按引用傳遞,用託管堆表

Python變數資料型別型別轉換

a.變數的定義   把資料分別用一個簡單的名字代表,方便在接下來的程式中引用。   變數就是代表某個資料(值)的名稱。   變數就是用來儲存資料的,將不同的資料型別儲存到記憶體   b.變數的賦值 變數名= 初始值 初始值:為了確定變數的型

Unity NavMesh尋路檢測的bug(或者特性),爬坡卡住問題(角色高度網格高度一致造成)

Unity專案,由於人物移動時一般用搖桿或者方向鍵控制, 需要有八方向方式控制朝向,  所以沒有用 NavMesh Agent, 而是自己控制人物方向移動,然後貼合地面。 用了NavMesh.CalculatePath只是用於目標點的尋路, 尋找出路經後自己計算實現移動。

JAVA 程式設計題解與上機指導(第四版) 第二章·識別符號、關鍵字資料型別 2.12

/*2.12 設計實現一個MyGraphic類及子類,它們代表一些基本圖形,這些圖形包括矩形、三角形、圓、橢圓、菱形、梯形等。 試給能描述這些圖形所必需的屬性及必要的方法 **/ public class MyGraphic { String lineColor;//線條顏色 Strin

Java中JNI的使用詳解第二篇:JNIEnv型別jobject型別的解釋

上一篇說的是一個簡單的應用,說明JNI是怎麼工作的,這一篇主要來說一下,那個本地方法sayHello的引數的說明,以及其中方法的使用 首先來看一下C++中的sayHello方法的實現:  對於這個方法引數中的JNIEnv* env引數的解釋: JNIEnv型別實際上代表了Java

PHP變數的值型別引用型別

PHP 變數在記憶體中儲存的並不直接是值的內容而是值的地址。比如: $a = 1; 從表面上看起來似乎是 $a 直接儲存了 1 這個值。但是實際情況是,PHP 直譯器建立了變數 $a , 將值 1 存入記憶體中的某個地方,再將值的地址存到變數中。 需要取值時,先找到變數中 $a 的地址,再根

java中,方法引數是基本型別引用型別的區別

方法引數是基本型別時,傳遞的是值。 方法引數是引用型別時,傳遞的是記憶體地址值 當引數是基本型別時,在呼叫方法時將值傳遞到方法中,執行方法,執行結束方法退出,對原本main中定義的變數沒有任何操作(方法中沒有return)。即:此時只跟棧有關係,方法執行完之後(方法中沒有return),會彈棧。

基本型別引用型別區別指向問題

基本型別: null, undefined, string, boolean, number (存放在棧記憶體中) 引用型別: array, object (存放在堆記憶體中) 1. 基本型別指標問題 var a=2; var b=a; b=3; console.log(a);//

OpenCV Java 問題記錄 - Mat型別BufferedImage型別的相互轉化

將Mat型別轉化成BufferedImage型別 /** * 將Mat型別轉化成BufferedImage型別 *  * @param amatrix Mat物件 * @param fileExtension 副檔名 * @return */ public static Buffere

mysql的基本操作資料型別

一.初始mysql語句 操作資料夾   增 create database db1 charset utf8   查 #檢視當前建立的資料庫 show create database db1; #檢視所有的資料庫 show databases;   改 alter

js中值型別引用型別的區別(無舉例)

js中的變數型別有哪些? (1)值型別:字串string、數值number、布林值boolean、undefined (2)引用型別:物件object、陣列array、函式function 值型別和引用型別的區別 (1)值型別: 1⃣️佔用空間固定,儲存在棧中(當一個方法

int型別byte型別的強制型別轉換

OKevin GitBook:《探尋Java中的設計模式》 Mail:[email protected] 部落格園 首頁 新隨筆 聯絡 訂閱 管理 隨筆 - 130  文章 - 0  評論 - 83

Java- 04-變數資料型別

變數 變數可以持有基本型別或指向某個物件 變數必須先定義後使用 定義變數 變數可以被賦值,還可以被重新賦值 等號=是賦值,不是數學的相等 Eclipse Debug 進入除錯模式後可以設定斷點後單步執行 資料型別 整數型別:byt

基本型別引用型別作為引數傳遞(重要)

基本型別和引用型別作為引數傳遞 引用型別資料和基本型別資料作為引數傳遞有沒有差別呢?我們用如下程式碼進行說明,並配合圖解讓大家更加清晰 1.基本資料型別傳遞 基本型別作為引數傳遞時,其實就是將基本型別變數x空間中的值複製了一份傳遞給呼叫的方法show(),當在show()方法中

Python基礎學習---語法資料型別(一)

1 #!/usr/bin/python3 x="a" y="b" # 換行輸出 print( x ) print( y ) print('---------') # 不換行輸出 print( x, end=" " ) print( y, end=" " ) print()

go的靜態型別動態型別

      先來看個簡單的go程式: package main import ( "fmt" ) type TaskIntf interface { Process() } type Task struct { TaskId string X

型別 引用型別

值型別 /** 值型別**/ // number 型別 var a = 100 var b = a a = 200 console.log(b) //100 // string 型別 var s