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

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

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

3天內不再提示

C/C++靈魂拷問:++i與i++哪個執行效率高?有什么區別?

Q4MP_gh_c472c21 ? 來源:高效程序員 ? 作者:高效程序員 ? 2022-03-31 14:04 ? 次閱讀

背景:相信很多人都遇到過這樣的問題:printf("%d,%d",i++,++i); 也糾結過這個問題,到底答案是什么,都沒有一個參考的資料……而唯一知道的是,幾乎所有C語言教材都這么講:i++就是先使用i的值再使i自身加一,而++i則是先使i自身加一,然后在使用i的值。 出于對真理的追求,今天我們就徹底弄明白此問題! 譬如這樣的話:
int a,b;int i=10,j=10;a=i++;b=++j;

我們可以很清楚的知道a和b的值分別將是10和11。這點毫無疑問,因為無論在任何平臺任何編譯器上運行都是這個結果!

然而,對于這樣的程序:

int a,b;int i=10,j=10;a=(i++)+(i++)+(i++);b=(++j)+(++j)+(++j);

各位試想答案將是多少?我們可以放到編譯器上,運行看一下結果。

先來看看windows下常用的VC6結果:

3500f10a-b0b2-11ec-aa7f-dac502259ad0.jpg

嗯,看到了,是30和37。但這個結果好像有點怪…… 那就再看看Linux下gcc的結果:

3515d1f6-b0b2-11ec-aa7f-dac502259ad0.png

哦,竟然也是30和37!
那么,我們再看看古老一點的TurboC的結果:

352cd126-b0b2-11ec-aa7f-dac502259ad0.jpg

354074e2-b0b2-11ec-aa7f-dac502259ad0.jpg

結果成了30和39,還真有點怪。 當然,就C語言代碼來看,i++和++i都只有一行,看起來似乎二者的執行效率一樣了?其實不是的,在學習C語言時,教材和老師一般都會強調i++和++i的區別,例如下面這段C語言代碼:
inti,j,k;i = 0;j = i++;i = 0;k = ++i;
這段C語言代碼執行后,j和k的值并不相等:j等于0,k等于1。 既然執行結果有差異,那么執行效率很有可能也是有差異的,事實的確如此。 查看上述C語言代碼對應的匯編代碼,如下:

3553f83c-b0b2-11ec-aa7f-dac502259ad0.jpg

編譯器版本為gcc 4.8.4

可見,j=i++;計算機需要4條指令來解釋,比執行k=++i;多出了一條指令。多出的一條指令為:在對i執行自加操作之前,先保存i的當前值留作稍后使用(賦值為j)。

這是怎么回事呢?不同的編譯器結果還不一樣呢?

而且這樣看來,似乎++i的執行效率比i++高一些?

為什么不同的編譯器結果不一樣?
要說起這其中的原因,我們要先明白兩個知識點,即“副作用”與“順序點”。 這里我們引用《C Primer Plus》的說法:“現在我們再討論一些C的術語。副作用(side effect)是對數據對象或文件的修改。”
例如語句states=50,它的副作用是將變量states的值設置為50。這是副作用?這看起來更像是主要目的!然而,從C的角度來看,主要目的是對表達式求值。給C一個表達式4+6,C將計算它的值為10。給C一個表達式states=50,C將計算它的值為50。計算這個表達式的副作用就是把變量states的值改變為50。跟賦值運算符一樣,增量運算符和減量運算符也有副作用,它們主要由于副作用而被使用。
一個順序點(sequence point)是程序執行中的一點;在該點處,所有的副作用都在進入下一步之前被計算。在C中,語句里的分號標志了一個順序點。它意味著在一個語句中賦值運算符、增量預算符及減量運算符所做的全部改變必須在程序進入下一個語句前發生。任何一個完整的表達式的結束也是一個順序點。
什么是完整的表達式呢?一個完整的表達式(full expression)是這樣一個表達式—-它不是一個更大的表達式的子表達式。完整的表達式的例子包括一個表達式語句里的表達式和在一個while循環里作為判斷條件的表達式。
順序點幫助闡明后綴增量動動作何時發生,比如考慮下面的代碼:
while(guests++<10)printf(“%d
”,guests);

有時C的初學者會設想在本程序中“先使用該值,然后增加它的值”的意思是在使用printf()語句后在增加guests的值。然而,因為guests++<10是while循環的判斷條件,所以它是一個完整的表達式,這個表達式的結束就是一個順序點。

因此,C保證副作用(增加guests的值)在程序進入printf()前發生。同時使用后綴形式保證了guests在于10比較后才增加。


現在考慮這個語句:

Y=(4+ x++)+(6+ x++);

表達式4+x++不是一個完整的表達式,所以C不能保證在計算子表達式4+x++后立即增加x。這里完整表達式是整個賦值語句,并且分號標記了順序點,所以C能保證的是在程序進入后續語句前x將增加兩次。C沒有指明x是在每個子表達式被計算后增加還是在整個表達式被計算后增加,這就是我們要避免使用這類語句的原因。

這是《C Primer Plus》的說法,相信您應該有一定答案了。


沒錯,那就是對于i=10;(++i)+(++i)+(++i);這樣的語句。C語言標準并沒有作規定。有的編譯器計算出來是39,因為會使i的值自增三次變為13,然后使用增加三次之后,也就是13的3個值相加為39。而有的編譯器計算結果則為37,如VisaulC++6.0則會先計算前兩個i的值為12,第三個i的值變成了加三次以后的值為13,因此結果是12+12+13=37。

如果有心的話,您可以分別在VC6和TC上本別測試;(++i)+(++i)+(++i)+(++i)的值來洞悉不同編譯器的處理規則。

那么,回到最初的printf的問題,明白求值的順序之后,再來看printf的求值問題,printf的參數都是從左到右依次壓入棧內,所以計算起來求值運算的時候則是由右至左(棧的特點:即先進后出)。那么至此,想必您已經完全想明白了這類問題的全部了!

所以講到這里,想必大家就清楚緣由了,不同編譯器的處理過程是不同的。所以并沒有唯一的標準答案!現在大家明白了嗎?

為什么++i比i++執行效率高一些呢? 為了寫出效率更高的C語言程序,以后是不是應該盡量使用++i,而不是i++了呢?例如下面這樣的C語言代碼:
for(i=0; i<10; i++);for(i=0; i<10; ++i);
是不是上面那行C語言代碼的執行效率低于下面的呢?只能說理論如此,實際上,現代C語言編譯器已經足夠聰明,它會根據上下文編譯C語言代碼。 應該明白,i++和++i的效率差異主要來自于處理i++時,需要先保存i的當前值留作稍后使用。如果之后沒有人使用i的當前值,也就是說沒有C語言代碼讀取i++的值,編譯器實在沒有必要保存i的當前值了,因此就會將這一步優化掉。 為了便于分析,我們編寫下面這樣的C語言代碼:
int i = 0;i++;++i;
與上面的例子相比,區別在于在執行i++時,沒有人關心i的當前值了。查看這段C語言代碼對應的匯編代碼:

3567966c-b0b2-11ec-aa7f-dac502259ad0.png

顯然,i++和++i對應的指令是一模一樣的,不再有執行效率上的差異。 C語言中的i++和++i是有區別的,這就有可能帶來效率上的差異。如果有代碼關心i++執行時的i當前值,程序在對i進行自加操作時,將不得不先保存i的當前值,而++i就無需保存當前值,這就會帶來效率上的差異。如果沒人關心i++的當前值,那么現代大多數C語言編譯器將會將這一差異優化掉,此時i++和++i不再有效率上的差異。

審核編輯 :李倩

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

    關注

    180

    文章

    7628

    瀏覽量

    139881
  • C++
    C++
    +關注

    關注

    22

    文章

    2116

    瀏覽量

    74621
  • 編譯器
    +關注

    關注

    1

    文章

    1653

    瀏覽量

    49757

原文標題:C/C++靈魂拷問:++i與i++哪個執行效率高?有什么區別?

文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。

收藏 0人收藏

    評論

    相關推薦
    熱點推薦

    I2C總線復用

    帝晶智慧屏I2C總線復用
    的頭像 發表于 03-11 17:20 ?1238次閱讀

    I2C總線與Arduino的接口示例

    在現代電子設計中,I2C總線因其簡單性和靈活性而廣受歡迎。它允許多個設備共享同一通信線路,從而節省空間和成本。Arduino,作為一個多功能的微控制器平臺,自然也支持I2C通信。 I2C總線
    的頭像 發表于 01-17 15:34 ?1149次閱讀

    I2C總線應用實例分析

    在現代電子系統中,I2C總線因其簡單、靈活和高效的特點而被廣泛應用于各種設備之間的通信。 I2C總線概述 I2C總線由Philips(現為NXP)在1980年代初期開發,最初用于音頻和視頻設備
    的頭像 發表于 01-17 15:09 ?515次閱讀

    AN-686: 實現I2C復位

    電子發燒友網站提供《AN-686: 實現I2C復位.pdf》資料免費下載
    發表于 01-15 16:26 ?0次下載
    AN-686: 實現<b class='flag-5'>I</b>2<b class='flag-5'>C</b>復位

    AN-913: I2C接口的隔離

    電子發燒友網站提供《AN-913: I2C接口的隔離.pdf》資料免費下載
    發表于 01-13 15:10 ?0次下載
    AN-913: <b class='flag-5'>I</b>2<b class='flag-5'>C</b>接口的隔離

    同樣是函數,在CC++中有什么區別

    同樣是函數,在 CC++ 中有什么區別? 第一個返回值。 C語言的函數可以不寫返回值類型,編譯器會默認為返回 int。 但是 C++
    的頭像 發表于 11-29 10:25 ?720次閱讀

    AIC3254的miniDSP編寫代碼和編寫C5502代碼什么區別

    問題:AIC3254的miniDSP編寫代碼和編寫C5502代碼什么區別執行速度和代碼量來進行分析吧,謝謝回復
    發表于 11-06 07:22

    RISC V的I2C操作

    接口處理top接口output ? ? ?system_i2c_0_io_sda_writeEnable,output ? ? ?system_i2c_0_io_sda_write,input
    的頭像 發表于 11-01 11:06 ?560次閱讀

    C語言和C++中結構體的區別

    同樣是結構體,看看在C語言和C++中有什么區別
    的頭像 發表于 10-30 15:11 ?592次閱讀

    詳解I2C總線與SPI總線的區別

    I2C(Inter-Integrated Circuit)表示集成電路互連,是一種用于線路板內部芯片之間通信的總線。
    的頭像 發表于 10-16 15:16 ?1.3w次閱讀
    詳解<b class='flag-5'>I2C</b>總線與SPI總線的<b class='flag-5'>區別</b>

    I2C基本指南

    電子發燒友網站提供《I2C基本指南.pdf》資料免費下載
    發表于 09-10 09:40 ?0次下載
    <b class='flag-5'>I2C</b>基本指南

    優秀實踐:I3C共享總線上的I2C器件

    電子發燒友網站提供《優秀實踐:I3C共享總線上的I2C器件.pdf》資料免費下載
    發表于 09-06 09:49 ?0次下載
    優秀實踐:<b class='flag-5'>I3C</b>共享總線上的<b class='flag-5'>I2C</b>器件

    如何調試I2C

    電子發燒友網站提供《如何調試I2C.pdf》資料免費下載
    發表于 08-27 10:38 ?0次下載
    如何調試<b class='flag-5'>I2C</b>

    使用C2000 I2C模塊連接EEPROM

    電子發燒友網站提供《使用C2000 I2C模塊連接EEPROM.pdf》資料免費下載
    發表于 08-27 09:53 ?0次下載
    使用<b class='flag-5'>C</b>2000 <b class='flag-5'>I2C</b>模塊連接EEPROM

    C++中實現類似instanceof的方法

    C++多態與繼承,但是很多人開始學習C++,有時候會面臨一個常見問題,就是如何向下轉型,特別是不知道具體類型的時候,這個時候就希望C++ 可以向Java或者Python中有insta
    的頭像 發表于 07-18 10:16 ?805次閱讀
    <b class='flag-5'>C++</b>中實現類似instanceof的方法
    主站蜘蛛池模板: 依恋影院在线观看 | 人体内射精一区二区三区 | 娇小亚裔被两个黑人 | 少妇性饥渴BBBBBBBBB | 亚洲区偷拍自拍29P 亚洲区视频在线观看 | 久久这里只有精品2 | 色橹橹欧美在线观看视频高 | 麻花传媒XK在线观看 | 日本高清免费看 | 青苹果乐园在线观看电视剧 | 在线观看免费精品国产 | 一本二卡三卡四卡乱码麻豆 | 伊人影院2019 | 野花社区WWW韩国日本 | 国产精品人妻无码77777 | 鸡鸡插屁股 | 久久黄色免费 | 打卡中国各地奋斗第一线 | 日本电影小姐 | 国产成人精品精品欧美 | 国自精品三七区 | 久青草国产观看在线视频 | 久久成人a毛片免费观看网站 | 在线综合 亚洲 欧美 | 成人区精品一区二区不卡AV免费 | 寂寞夜晚免费观看视频 | 成片在线看一区二区草莓 | 亚洲乱色视频在线观看 | 欧美三级黄色大片 | 99福利在线| 国产成人精品亚洲线观看 | 日本伦理片 中文字幕 | 国产亚洲精品久久久久久入口 | 91av欧美| 国产人妻人伦精品久久无码 | 嗨嗨快播电影 | 噜噜噜在线AV免费观看看 | 99国产精品久久久久久久日本竹 | 国产爱豆果冻传媒在线观看视频 | 久草在线在线精品观看99 | 久久久久久久网站 |

    電子發燒友

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

    • 2931785位工程師會員交流學習
    • 獲取您個性化的科技前沿技術信息
    • 參加活動獲取豐厚的禮品