关于C语言中printf函数“输出歧视”的问题
目錄
- 關于C語言中printf函數“輸出歧視”的問題
- 問題描述
- 探索問題原因
- 另一種研究方法
- 問題結論
關于C語言中printf函數“輸出歧視”的問題
問題描述
昨天晚上被問到一個問題,為什么在同一個printf函數中兩次輸出一個double型變量會得不到正確的結果。具體代碼大致如下:
#include <stdio.h>int main()
{int a;double b;double result;printf("Please input a: ");scanf("%d", &a);printf("Please input b: ");scanf("%lf", &b);printf("\n");result = a * b;printf("result_int: %d\nresult_double: %f\n", result, result);return 0;
} 看主函數的第18行語句,其中result作為一個double型變量,被以整型和浮點型分別輸出了一次,按照正常思路,輸出應該是下面這樣:
Please input a: 12
Please input b: 12.3result_int: 858993460
result_double: 147.600000 即前一個按整型輸出時,會按照double型低32位的數據,輸出一個不期望的整數。
但是第二次輸出時,則會按照其正確的形式(64位8字節double類型)輸出一個預期中的浮點數:147.600000。
結果卻大出意料,實際輸出是下面這樣:
Please input a: 12
Please input b: 12.3result_int: 858993460
result_double: 0.000000 探索問題原因
這樣的結果讓人很意外,第一時間就想到了是否是因為result本身出了問題,所以在原程序后加入了一句printf("\n%f\n", result);來確認result是否發生了意料之外的變化。
但是很顯然,并不是result出了問題,因為單獨輸出的result依然是正常的147.600000。
那么接下來,既然result本身沒有問題,就應當想到是否在輸出上出了問題。比如很顯然地,%d格式是標準的Int型輸出格式,正常來講應該是32位數據,而double則是64位數據,是否是這里出了問題呢?
比如在同一句輸出里面,對同一個變量多次不完整輸出,導致了其地址的遞進式輸出。
當然,到此時,這只是我的一種猜測。
要驗證這個想法,最簡單的莫過于直接查看內存內容。
如圖
轉換為4字節整數顯示結果為
與輸出
result_lower_32 = 858993459
result_higher_32 = 1080193843
resule_now = 147.600000 相符。
到此,產生這一問題的原因已經弄清楚了,并且最終問題應該是出在printf函數的定義中,看來還是C語言基礎不牢,今天開始有必要重新學習,認真研究其每個細節。
另一種研究方法
實際上一開始因為不太熟悉VS的調試操作,并沒能很快地在調試界面找到方法查看具體變量的內存地址及其內容,原因一則是很久沒有用C語言了,二則當初學的時候也沒有認真,所以驗證這個問題的過程十分艱辛,
中間還自己寫了個函數想要輸出數據的二進制格式,但是這個函數針對整型時工作正常,換成double型之后,由于沒想到辦法對double型和unsigned long long型直接進行位運算,所以迫不得已對double型數據進行了強制類型轉換,最終發現強制類型轉換會導致數據變化,無法保持其原型,所以這一思路作廢。就此略過不表。
后來想起來C語言中可以對數據直接按16進制格式輸出,故設計了如下程序進行嘗試。
#include <stdio.h>int main()
{//該系統中,double為64位8字節,int和long為32位4字節。//且為小端系統,即低位數據存儲在內存的低位地址中。double b;printf("Please input the values of b:\n");scanf("%lf", &b);printf("\n");printf("These are two parts of b:\n");printf("\tlower byte = \t%#x\n\thigher byte = \t%#x\n\n", b, b);printf("This is the whole b:\n");printf("\t%#llx\n", b);return 0;
}
輸出如下(輸入為12.3)
Please input the values of b:
12.3These are two parts of b:lower byte = 0x9999999ahigher byte = 0x40289999This is the whole b:0x402899999999999a 問題結論
從上述兩種研究方法的結果,我們可以明顯看到,在同一個輸出格式字符串中,倘若針對某一個待輸出量的轉換說明不足以對應其所有的數據位,則printf函數僅僅按照轉換說明對應的數據位數,從低到高,依次輸出。
所以對于介于初學和中級之間的學習者而言,研究stdio.h頭文件的源碼函數很有必要的。
轉載于:https://www.cnblogs.com/lierchao/p/10003639.html
總結
以上是生活随笔為你收集整理的关于C语言中printf函数“输出歧视”的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 宜家通信- 会员管理 表结构搭建
- 下一篇: 洱海桃源码头游船时刻表