色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

關于你可能不知道的printf

黃工的嵌入式技術圈 ? 來源:黃工的嵌入式技術圈 ? 作者:黃工的嵌入式技術 ? 2020-02-05 12:28 ? 次閱讀

前言

printf可能是我們在學習C語言的過程中最早接觸的庫函數了。其基本使用想必我們都已經非常清楚了。但是下面的這些情況你是否已經清楚地知道了呢?

示例程序

我們來看一個示例程序,看看你能否對下面的結果輸出有非常清晰的認識。

#include intmain(void) { inta=4; intb=3; intc=a/b; floatd=*(float*)(&c); longlonge=0xffffffffffffffff; printf("a/b:%f,a:%d\n",a/b,a,b);//打印0 printf("(float)a/b:%f\n",((float)a)/b);//打印1 printf("(double)a/b:%lf\n",((double)a)/b);//打印2 printf("d:%f\n",d);//打印3 printf("%.*f\n",20,(double)a/b);//打印4 printf("e:%d,a:%d\n",e,a);//打印5 printf("a:%d,++a:%d,a++:%d\n",a,++a,a++);//打印6 return0; }

編譯為32位程序:

gcc-m32-otesttest.c

在運行之前,你可以自己先猜想一下打印結果會是什么。實際運行結果:

a/b:0.000000,a:3//打印0的結果 (float)a/b:1.333333//打印1的結果 (double)a/b:1.333333//打印2的結果 d:0.000000//打印3的結果 1.33333333333333325932//打印4的結果 e:-1,a:-1//打印5的結果 a:6,++a:6,a++:4//打印6的結果

你的猜想是否都正確呢?如果猜想錯誤,那么接下來的內容你就不應該錯過了。

你是否會有以下疑問:

0.打印0的a/b為什么不是1,a為什么不是4?

1.打印1和打印2有什么區別呢?

2.打印3為什么結果會是0.000000?

3.打印4的結果為什么最后的小數位不對?其中的*是什么意思?

4.打印5中,為什么a的值是-1而不是4?

5.打印6中,結果為什么分別是6,6,4?

在解答這些問題之前,我們需要先了解一些基本內容。

可變參數中的類型提升

printf是接受變長參數的函數,傳入printf中的參數個數可以不定。而我們在變長參數探究中說到:
調用者會對每個參數執行“默認實際參數提升",提升規則如下:
——float將提升到double
——char、short和相應的signed、unsigned類型將提升到int

也就是說printf實際上只會接受到double,int,long int等類型的參數。而從來不會實際接受到float,char,short等類型參數。
我們可以通過一個示例程序來檢驗:

//badcode #include intmain(void) { char*p=NULL; printf("%d,%f,%c\n",p,p,p); return0; }

編譯報錯如下:

printf.c:Infunction‘main’: printf.c:5:12:warning:format‘%d’expectsargumentoftype‘int’,butargument2hastype‘char*’[-Wformat=] printf("%d,%f,%c\n",p,p,p); ^ printf.c:5:12:warning:format‘%f’expectsargumentoftype‘double’,butargument3hastype‘char*’[-Wformat=] printf.c:5:12:warning:format‘%c’expectsargumentoftype‘int’,butargument4hastype‘char*’[-Wformat=]

我們可以從報錯信息中看到:

%d 期望的是 int 類型參數

%f 期望的是 double 類型參數

%c 期望的也是 int 類型參數

而編譯之所以有警告是因為,char *類型無法通過默認實際參數提升,將其提升為int或double。

參數入棧順序以及計算順序

在C語言中,參數入棧順序是確定的,從右往左。而參數的計算順序卻是沒有規定的。也就是說,編譯器可以實現從右往左計算,也可以實現從左往右計算。

浮點數的有效位

對于double類型,其有效位為15~~16位(參考:對浮點數的一些理解)。

可變域寬和精度

printf中,*的使用可實現可變域寬和精度,使用時只需要用*替換域寬修飾符和精度修飾符即可。在這樣的情況下,printf會從參數列表中取用實際值作為域寬或者精度。示例程序如下:

#include intmain(void) { floata=1.33333333; char*p="hello"; printf("%.*f\n",6,a); printf("%*s\n",8,p); return0; }

運行結果:

1.333333 hello

而這里的6或者8完全可以是一個宏定義或者變量,從而做到了動態地格式控制。

格式控制符是如何處理參數的

printf有很多格式控制符,例如%d,它在處理輸入時,會從堆棧中取其對應大小,即4個字節作為對應的參數值。也就是說,當你傳入參數和格式控制符匹配或者在經過類型提升后和格式控制符匹配的時候,參數處理是沒有任何問題的。但是不匹配時,可能會出現未定義行為(有兩種情況例外,我們后面再說)。例如,%f期望一個double(8字節)類型,但是傳入的參數是int(4字節),那么在處理這個int參數值,可能會多處理4個字節,并且也會造成處理數據錯誤。

真相大白

有了前面這些內容的鋪墊,我們再來解答開始的疑問:

對于問題0,a/b的結果顯然為4字節的int類型1,而%f期望的是8字節的double,而計算結果只有4個字節,因此會繼續格式化后面4個字節的a,而整型1和后面a組合成的8字節數據,按照浮點數的方式解釋時,它的值就是0.000000了。由于前面已經讀取解釋了a的內容,因此第二個%d只能繼續讀取4個字節,也就是b的值3,最終就會出現打印a的值是3,而不是4。

對于問題1,實際上在printf中,是不需要%lf的,%f期望的就是double類型,在編譯最開始的示例程序其實就可以發現這個事實。當然了在scanf函數中,這兩者是有區別的。

對于問題2,也很簡單,2的二進制存儲形式按照浮點數方式解釋讀取時,就是該值。

對于問題3,double的有效位為15~16位,也就是之外的位數都是不可靠的。printf中的*可用于實現可變域寬和精度,前面已經解釋過了。

對于問題4,這里不給出,留給讀者思考,歡迎大家可留言區給出原因。

對于問題5,雖然參數計算順序沒有規定,但是實際上至少對于gcc來說,它是從右往左計算的。也就是說,先計算a++,而a++是先用在加,即壓入a=4,其后,a的值變為5;再計算++a,先加再用,即壓入a=5+1=6;最后a=6,壓入棧。最終從左往右壓入棧的值就分別為6,6,4。也就是最終的打印結果。但是實際情況中,這樣的代碼絕對不該出現!

至此,真相大白。

總結

雖然我們前面解釋了那些難以理解的現象,同時讀者可以參考變長參數探究和對浮點數的一些理解找到更多的信息。但是我們在實際編程中應該注意以下幾點:

格式控制符應該與對應參數類型匹配或者與類型提升后的參數類型匹配。

絕對避免出現計算結果與參數計算順序有關的代碼。

*在printf中實現可變域寬和精度。

printf不會實際接受到char,short和float類型參數。

如果%s對應的參數可能為NULL或者對應整型,那將是一場災難。

不要忽略編譯器的任何警告,除非你很清楚你在做什么。

例外情況指的是有符號整型和無符號整型之間,以及void*和char*之間。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 打印
    +關注

    關注

    1

    文章

    66

    瀏覽量

    18848
  • 程序
    +關注

    關注

    117

    文章

    3815

    瀏覽量

    81905
  • Printf
    +關注

    關注

    0

    文章

    83

    瀏覽量

    13936
收藏 0人收藏

    評論

    相關推薦

    ADS805E測量跳躍幅度很大,不知道是為什么?

    我按照手冊上直流耦合連接電路,輸入是1.5V~3.5V范圍,SEL與VREF相連,用430定時器輸出轉換時鐘,結果測量直流時,AD測量結果在幾個值之間跳躍,跳躍幅度很大,不知道是為什么,引腳電壓控制用3.3V。
    發表于 01-21 07:46

    測的值不定然后開始減小直到為0,不知道怎么回事?

    ADS1247對寄存器可讀可寫 可是配置完02這個地址的時(寫0x30)在vrefout測不到2.048v,測的值不定然后開始減小直到為0,不知道怎么回事?
    發表于 01-21 06:27

    有關UV固化不知道的技術細節

    UV固化技術中,光引發劑吸收UV光產生活性自由基觸發聚合反應,包括鏈引發、增長、終止和交聯。反應速率受UV光強、光引發劑濃度、單體類型等因素影響,UV固化技術具有快速固化特性。
    的頭像 發表于 12-06 09:33 ?459次閱讀

    盤點Linux系統中的常見命令

    作為運維同學怎能不知道Linux系統中的lsmod、lsof、lspci、lsscsi命令呢,今天就來盤一盤她及實例。
    的頭像 發表于 12-03 09:48 ?551次閱讀
    盤點Linux系統中的常見命令

    關于陶瓷電路板不知道的事

    陶瓷電路板(Ceramic Circuit Board),又稱陶瓷基板,是一種以陶瓷材料為基體,通過精密的制造工藝在表面形成電路圖形的高技術產品,快來看看哪些是您還不知道的事?
    的頭像 發表于 10-21 11:55 ?670次閱讀
    <b class='flag-5'>關于</b>陶瓷電路板<b class='flag-5'>你</b><b class='flag-5'>不知道</b>的事

    又一電工不知道,施耐德變頻器怎么復位,如果不告訴,知道怎么復位嗎?

    維修 我給他說,可能以前沒接觸過施耐德的變頻器,就不知道它還有一個蓋子,要復位的話,就要把蓋子打開,第一次找不到也正常,要是經常斷電重啟的話,對設備不好。 變頻器修理 之所以分享給大家,就是想告訴那些沒接觸過施耐
    的頭像 發表于 10-12 15:15 ?700次閱讀
    又一電工<b class='flag-5'>不知道</b>,施耐德變頻器怎么復位,如果不告訴<b class='flag-5'>你</b>,<b class='flag-5'>你</b><b class='flag-5'>知道</b>怎么復位嗎?

    使用CS1232 采集一個小信號,信號有可能是正,也可能是負 ,是不知道怎么回事情?

    我使用CS1232 采集一個小信號,信號有可能是正,也可能是負 但是不知道怎么回事情,采集的數據就經常不對 在上圖的電路中,當我把P4 短路,采集到的電壓盡然是為8388608 我看了一下SDO
    發表于 09-25 14:36

    鳳凰動力告訴,知道不知道的AGV類型都在這里了

    的一部分。本文將盡可能多地羅列出AGV小車的各種類型,并簡要介紹其工作原理。 一、潛伏舉升式AGV 潛伏舉升式AGV是一種特殊的AGV類型,其特點是車體低矮,可以在貨架下方潛伏行駛。當需要取貨或放貨時,車體可以舉升一定高度,以便進行貨物操作。
    的頭像 發表于 09-14 09:09 ?753次閱讀
    鳳凰動力告訴<b class='flag-5'>你</b>,<b class='flag-5'>知道</b><b class='flag-5'>不知道</b>的AGV類型都在這里了

    知道貼片電感故障時可能出現的癥狀嗎?

    知道貼片電感故障時可能出現的癥狀嗎?
    的頭像 發表于 08-17 14:20 ?571次閱讀
    <b class='flag-5'>你</b><b class='flag-5'>知道</b>貼片電感故障時<b class='flag-5'>可能</b>出現的癥狀嗎?

    AMC1100使用前需要烘烤,不知道烘烤溫度和烘烤時間是多少?

    1:AMC1100使用前需要烘烤,但是不知道 烘烤溫度和烘烤時間是多少?能在datasheet上查看到嗎? 2:datasheet上 MSL參數 Level-1-260C-UNLIM中UNLIM
    發表于 08-09 08:11

    新手嘗試做一個LED驅動電路,不知道電路有沒有問題

    TP8006穩流驅動,最后留出LED插口。 因為不是很懂硬件設計,不知道做的模塊能不能行,很希望各位提提意見,讓我認識認識硬件設計上的缺陷。
    發表于 07-24 18:35

    不知道怎么進行負載測試發電機嗎?

    測試一般的流程是怎樣的,知道嗎? ? 1、試驗前準備:確保發電機和試驗設備處于良好的工作狀態,檢查發電機的電源和燃料供應是否正常,確保試驗設備與發電機的連接正確可靠。 2、確定試驗載荷:根據您的實際要求確定試驗
    的頭像 發表于 07-03 17:36 ?1247次閱讀

    這些不知道的臥式共模電感的選型依據

    這些不知道的臥式共模電感的選型依據 gujing 編輯:谷景電子 實際上關于臥式共模電感的選型已經有討論過很多這方面的內容,但一直都還有人在討論這些問題。本篇我們換幾個角度來探討一下臥式共模電感
    的頭像 發表于 04-29 22:42 ?471次閱讀

    STM8L051片子使用重定向printf函數時總是報錯,沒辦法引用printf函數是什么原因?

    STM8L051片子使用重定向printf函數時總是報錯,沒辦法引用printf函數,不知道是什么原因,使用的是IAR編譯器,總是報內存不足的錯誤,,求大神指導
    發表于 04-28 08:05

    沒用過zynq今天在看解析是發現汽車的CID上有用這個,不知道zynq有什么優勢?

    沒用過zynq今天在看解析是發現汽車的CID上有用這個,不知道zynq有什么優勢?
    發表于 04-23 15:01

    電子發燒友

    中國電子工程師最喜歡的網站

    • 2931785位工程師會員交流學習
    • 獲取您個性化的科技前沿技術信息
    • 參加活動獲取豐厚的禮品
    主站蜘蛛池模板: 99精品网站 | 好吊妞国产欧美日韩视频 | 99视频免费观看 | 在线精品视频成人网 | 日韩人妻无码精品久久中文字幕 | 国产精品视频免费观看 | 国产成人无码WWW免费视频在线 | 国产免费人成在线视频有码 | 中文字幕久久熟女人妻AV免费 | 国内卡一卡二卡三免费网站 | 国产树林野战在线播放 | 久久香蕉国产免费天天 | 欧美亚洲国产激情一区二区 | 日韩欧美精品有码在线播放免费 | 一个人在线观看免费视频 | 日本xxxx19| 久久只有这里有精品4 | 国产成人无码一区AV在线观看 | 中文字幕国产在线观看 | 一一本之道高清视频在线观看中文字幕 | 国产免费人成在线视频有码 | 久久频这里精品99香蕉久网址 | 花蝴蝶hd免费 | 最近免费中文字幕MV在线视频3 | 国产精品久久久久久久久无码 | 国产69精品久久久久人妻刘玥 | 农民下乡在线观看3 | 九九精彩视频在线观看视频 | 把极品白丝班长啪到腿软 | 亚洲视频在线看 | 国产Av影片麻豆精品传媒 | 国产精品18久久久久久欧美 | 68日本xxxxxxxx79| 新金梅瓶玉蒲团性奴3 | 91麻豆久久| 特大巨黑人吊性xxxxgay | 国产在线播放精品视频 | 中文字幕精品无码一区二区 | 国产毛片AV久久久久精品 | 亚洲不卡视频 | 国产精品在线手机视频 |