乙個printf引發的問題

2021-07-16 05:36:24 字數 1448 閱讀 4670

牛客網上的乙個題目:

intmain()

看起來挺簡單的,牽扯的東西比較多。

這是我的思路:

printf函式執行的時候,會先把這三個數字壓入棧裡,然後再執行列印。壓入棧的時候按照資料本身的長度來,首先把c和b壓入,並且每乙個都是8個位元組(printf自動轉化為double)。然後再壓入a是4個位元組。然後再執行列印。列印的時候按照使用者指定的格式來出棧。首先列印a,a列印正常。然後又列印4個位元組長度的b,在棧裡面由於b長度是八個位元組,並且b目前是64位的表示方式,資料的後面全是0.(float 變double),電腦是小端儲存方式,0儲存在距離a近的地方。列印b的時候,列印的4個位元組都是0.然後再列印c,c用正常的方式列印,會一下子讀取8個位元組,正好,讀出來的八個位元組前面四個位元組全是0,自己可以算一下,實在太小了,因此為0.

棧底                                          棧頂

高位元組。。。。。。。。。。。低位元組

4321     0000      765     0000         98

4位元組   4位元組    4位元組    4位元組      4位元組

列印c                 列印b      列印a

附:浮點數(單精度的float和雙精度的double)在記憶體中以二進位制的科學計數法表示,表示式為n = 2^e * f;其中e為階碼(採用移位儲存),f為尾數。

float和double都由符號位、階碼、尾數三部分組成,float儲存時使用4個位元組,double儲存時使用8個位元組。各部分占用位寬如下所示:

符號位     階碼      尾數     長度

float              1           8         23      32

double          1         11        52       64

舉例子:765.0這個浮點數,這文章中需要轉換成64位精度,首先將765轉換成二進位制 1011111101

然後轉換成階碼的形式    1.011111101  *   2^(9)

這裡的9轉換成11位的階碼為  1023+9=(10000001000),如果是32位的float只需要加127

加上符號位為0,再加上後面的尾數(只取小數部分011111101000)最後得到 的數為  4087e800

在vs中如何檢視?

首先進入除錯,然後單步除錯,在呼叫堆疊的地方右鍵進入反彙編 ,如圖:

esp是棧的指標,在這可以看到減8的操作,就是入棧的操作。dword ptr[esp]就是對應位址的資料

cvtss2sd是將float轉化成double型別的,執行完後可以看一下xmm0的資料

結果正是 4087e800

乙個printf函式引發的宕機

今天同事解決了乙個問題,頗有啟發,拿出來共賞之。char str printf str 如果這樣寫,會編譯不過 printf str s n 因為引數不夠。可是你有沒有考慮過下面這種情況?char str im a good man s n printf str 這段程式碼是可以編過並執行的,但是。...

乙個索引引發的問題

215 上了乙個大表的組合索引,引發了查詢sql的執行計畫混亂,最終cpu充到100 業務系統掛掉,庫也幾乎宕掉。1,為什麼建了索引後,oracle執行計畫會亂掉,而且選擇了乙個最慢的執行計畫?dba答覆 表關聯!關聯表越多,oracle選擇執行計畫出錯的概率變大!如何防止此類事件 上索引之前,先固...

乙個content type引發的問題

背景介紹 問題 報警監控顯示專案的活動介面異常並報錯,提示json decode解析異常,但不必現,無法立刻判斷原因。先介紹下我們的資料傳遞流程 監控時常顯示專案的某個介面報錯異常,報警提示如下 圖2.報警郵件 過程分析 很明顯,json decode post result 出錯,解析的資料格式非...