0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C語(yǔ)言那些"令人震驚"的結(jié)構(gòu)分析

GReq_mcu168 ? 來(lái)源:CSDN技術(shù)社區(qū) ? 作者:CSDN技術(shù)社區(qū) ? 2020-10-09 11:58 ? 次閱讀

C語(yǔ)言會(huì)同意一些"令人震驚"的結(jié)構(gòu),下面的結(jié)構(gòu)是合法的嗎,我們來(lái)看看幾個(gè)例子。

c = a+++b;

以下代碼是合法的嗎,咋的一看不禁有這樣的疑問(wèn)?

inta=5,b=7,c; c=a+++b;

這個(gè)代碼確實(shí)不咋符合習(xí)慣的寫(xiě)法,但是不管你相不相信,上面的例子是完全合乎語(yǔ)法的。問(wèn)題是編譯器如何處理它?

根據(jù)最處理原則,編譯器應(yīng)該能夠盡可能處理所有合法的用法。因此,上面的代碼會(huì)被處理成:

c=a+++b;

我們來(lái)測(cè)試一下:

//https://tool.lu/coderunner/ //來(lái)源:技術(shù)讓夢(mèng)想更偉大 //作者:李肖遙 #include intmain() { inta=5,b=7,c; c=a+++b; printf("a=%d,b=%d,c=%d",a,b,c); return0; }

輸出結(jié)果如下:

其執(zhí)行順序:

b不變,c = a + b;,則c = 5 + 7 = 12

a++,那么a = 6;

c = a+++++b;

上面那么可能只是開(kāi)胃菜,那么這個(gè)表達(dá)式呢,有什么想法?咱們二話(huà)不說(shuō),直接上代碼測(cè)試。

//https://tool.lu/coderunner/ //來(lái)源:技術(shù)讓夢(mèng)想更偉大 //作者:李肖遙 #include intmain() { inta=5,b=7,c; c=a+++++b; //c=(a++)+(++b); //c=((a++)++)+b; printf("a=%d,b=%d,c=%d",a,b,c); return0; }

編譯結(jié)果如下:

雖然一看就知道意思是(a++)+(++b);,但是編譯就通不過(guò),我們把括號(hào)加上,c = (a++) + (++b);,編譯通過(guò),那么出錯(cuò)信息大概是:括號(hào)影響了優(yōu)先級(jí)?我們從側(cè)面以及原理來(lái)解析一下。

側(cè)面解析一下

對(duì)于a+++++b這一段代碼,編譯系統(tǒng)從左至右掃描整條語(yǔ)句,先遇到a++,判斷出來(lái)是一個(gè)a的后綴自加運(yùn)算;

然后接著掃描,遇到一個(gè)+,+是一個(gè)二目運(yùn)算符,它的左邊已經(jīng)有一個(gè)運(yùn)算數(shù)a++了,系統(tǒng)就向右搜索第二個(gè)運(yùn)算數(shù);

又遇到一個(gè)+,++比+的運(yùn)算級(jí)別要高,這時(shí),編譯系統(tǒng)就將兩個(gè)+看成一個(gè)整體來(lái)處理;

既然是++,編譯系統(tǒng)就認(rèn)定,肯定它的左邊或右邊有一個(gè)變量,編譯系統(tǒng)先搜索左邊,發(fā)現(xiàn)++,不是變量;

再搜索右邊,發(fā)現(xiàn)+b,+b是什么東西?編譯系統(tǒng)是無(wú)法搞明白的;

因此它就認(rèn)為++是一個(gè)缺少左值的自增運(yùn)算符,于是提示錯(cuò)誤給用戶(hù):lvalue required as increment operand

原理解析一下

C語(yǔ)言在這里遵循詞法解析的貪婪匹配原則。優(yōu)先匹配盡可能多字符的符號(hào),無(wú)論是否有語(yǔ)法錯(cuò)誤(因?yàn)樵~法分析時(shí)還沒(méi)有語(yǔ)法檢查)。

于是a+++++b會(huì)被當(dāng)作a ++ ++ + b,這是非法的表達(dá)式,因此產(chǎn)生編譯錯(cuò)誤。

這個(gè)問(wèn)題在ISO C99標(biāo)準(zhǔn)中直接以示例描述,原文如下:

EXAMPLE 2 The program fragment x+++++y is parsed as x ++ ++ + y, which violates a constraint onincrement operators, even though the parse x ++ + ++ y might yield a correct expression.

那么,也許是c = ((a++)++) + b;這個(gè)意思呢?

我們編譯結(jié)果依然報(bào)錯(cuò),如下:

這涉及到“左值”的問(wèn)題。百度百科定義如下:

左值(lvalue) 是B語(yǔ)言/C語(yǔ)言/C++語(yǔ)言等類(lèi)C語(yǔ)言中的一類(lèi)表達(dá)式?!白蟆?left)的原意是指可以放在賦值符號(hào)“=”的左邊,但其實(shí)也表示能作為&和++等操作符的操作數(shù)(B語(yǔ)言中已經(jīng)如此)。而且,現(xiàn)代C/C++中的含義已經(jīng)不局限于此。lvalue的l被重新解釋為location。這也對(duì)應(yīng)于ISO C11/ISO C++11的內(nèi)存位置(memory location)。

總結(jié):a存在左值,可以有表達(dá)式:a++。但是(a++)不存在左值,無(wú)法繼續(xù)執(zhí)行(a++)++操作,所以最終報(bào)錯(cuò)。

怎么樣才能編譯正確呢?

a+++++b在編譯時(shí)會(huì)報(bào)錯(cuò),那么a++ + ++b呢?來(lái)看以下代碼:

//https://tool.lu/coderunner/ //來(lái)源:技術(shù)讓夢(mèng)想更偉大 //作者:李肖遙 #include intmain() { inta=5,b=7,c; c=a+++++b; printf("a=%d,b=%d,c=%d",a,b,c); return0; }

結(jié)果如下:

其代碼與c = (a++) + (++b);結(jié)果一樣,說(shuō)明是正確的,其按照下面順序執(zhí)行:

先執(zhí)行b自加,b變?yōu)?;相當(dāng)于:b = b+ 1;

求a與b之和,賦給c;相當(dāng)于:c = a + b ;//c = 5+8;

執(zhí)行第二步之后,a自加1:a++;

c=(++a,b++,a++,++b);

這個(gè)表達(dá)式看著爽不爽?我們知道自增自減運(yùn)算,表示對(duì)自身進(jìn)行a=a+1或者a=a-1的運(yùn)算。

++a表示在調(diào)用前就a+1,a++表示在調(diào)用后+1。

int c=(++a,b++,a++,++b);這個(gè)逗號(hào)隔開(kāi)的表示用最后一個(gè)式子對(duì)C進(jìn)行賦值,測(cè)試如下:

//https://tool.lu/coderunner/ //來(lái)源:技術(shù)讓夢(mèng)想更偉大 //作者:李肖遙 #include intmain() { inta=5,b=7,c; c=(++a,b++,a++,++b); printf("a=%d,b=%d,c=%d",a,b,c); return0; }

輸出的結(jié)果如下:

這段執(zhí)行的順序如下

先執(zhí)行++a,a=6;

再執(zhí)行b++,b=8;

接下來(lái)a++,a=7;

再執(zhí)行++b,b=9;

把最后一個(gè)的式子b=9的值賦給c,所以c等于9。如果改成c=(++a,b++,a++,b++); ,那么c就是等于8,因?yàn)槭钦{(diào)用后再自增。

總結(jié)

我們看到這些有趣且不常見(jiàn)的代碼的時(shí)候,無(wú)需懷疑,只需要根據(jù)經(jīng)驗(yàn)一步一步分析,就會(huì)發(fā)現(xiàn)其中的玄妙之處。在此我總結(jié)以下幾點(diǎn)。

如果你一看就知道了答案,或猜出正確答案,說(shuō)明基礎(chǔ)做得好,點(diǎn)個(gè)贊。

如果你很猶豫,不知道答案,這也是正常的,因?yàn)楹苌僖?jiàn)到這樣寫(xiě)代碼的,但是我們也需要去了解,才能究其根源。

我總結(jié)這個(gè)問(wèn)題,是想提起一個(gè)關(guān)于代碼編寫(xiě)風(fēng)格,代碼的可讀性,代碼的可修改性的話(huà)題,這樣我們?cè)趯?xiě)代碼的時(shí)候才能夠注意到,更好的編碼。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7575

    瀏覽量

    134079

原文標(biāo)題:淺析C語(yǔ)言中一些“令人吃驚”的結(jié)構(gòu)

文章出處:【微信號(hào):mcu168,微信公眾號(hào):硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    C語(yǔ)言令人抓狂的一面——全局變量

    作為一名程序員,如果說(shuō)沉迷一門(mén)編程語(yǔ)言算作一種樂(lè)趣的話(huà),那么與此同時(shí)反過(guò)來(lái)去黑一門(mén)編程語(yǔ)言就是這種樂(lè)趣的升華。今天我們就來(lái)黑一把C語(yǔ)言,好好展示一下這門(mén)經(jīng)典
    發(fā)表于 01-16 11:07 ?397次閱讀

    C語(yǔ)言C++中那些不同的地方

    ++11標(biāo)準(zhǔn)。根據(jù)不同的標(biāo)準(zhǔn),它們的功能也會(huì)有所不同,但是越新的版本支持的編譯器越少,所以本文在討論的時(shí)候使用的C語(yǔ)言標(biāo)準(zhǔn)是C89,C++標(biāo)準(zhǔn)是C
    的頭像 發(fā)表于 12-07 14:29 ?773次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>和<b class='flag-5'>C</b>++中<b class='flag-5'>那些</b>不同的地方

    震驚啊,對(duì)癥下藥,網(wǎng)絡(luò)三“害蟲(chóng)”有治咯!

    `震驚啊,對(duì)癥下藥,網(wǎng)絡(luò)三“害蟲(chóng)”有治咯!超令人震驚,上網(wǎng)的親們,該來(lái)圍觀一下啦!網(wǎng)絡(luò)“三毒蟲(chóng)”,要對(duì)癥下藥,最新的網(wǎng)絡(luò)技術(shù)發(fā)明,老子終于能治你咯!大家都知道,路由器是網(wǎng)絡(luò)的第一道關(guān)口,也是網(wǎng)絡(luò)
    發(fā)表于 06-21 19:31

    漫談C語(yǔ)言結(jié)構(gòu)

    我放在下面?! ≡诖耍視?huì)圍繞以下2個(gè)問(wèn)題來(lái)分析和應(yīng)用C語(yǔ)言結(jié)構(gòu)體:  1. C語(yǔ)言中的
    發(fā)表于 11-15 15:59

    5G基礎(chǔ)設(shè)施發(fā)展有什么趨勢(shì)?

    我們目前處于蜂窩連接的轉(zhuǎn)型時(shí)期,未來(lái)無(wú)處不在的無(wú)線(xiàn)連接正在興起。在全球范圍內(nèi),2G、3G和4G的成功推動(dòng)手機(jī)使用量達(dá)到了令人難以置信的75億部。令人震驚的是,這使得移動(dòng)設(shè)備的數(shù)量比全球人口還要多
    發(fā)表于 08-01 08:06

    5G基礎(chǔ)設(shè)施和對(duì)端到端可編程性的需求有哪些?

    我們目前處于蜂窩連接的轉(zhuǎn)型時(shí)期,未來(lái)無(wú)處不在的無(wú)線(xiàn)連接正在興起。在全球范圍內(nèi),2G、3G和4G的成功推動(dòng)手機(jī)使用量達(dá)到了令人難以置信的75億部。令人震驚的是,這使得移動(dòng)設(shè)備的數(shù)量比全球人口還要多
    發(fā)表于 10-08 09:37

    數(shù)據(jù)結(jié)構(gòu)與算法分析(C語(yǔ)言版)

    電子發(fā)燒友網(wǎng)站提供《數(shù)據(jù)結(jié)構(gòu)與算法分析(C語(yǔ)言版).txt》資料免費(fèi)下載
    發(fā)表于 11-28 11:05 ?0次下載

    數(shù)據(jù)結(jié)構(gòu)與算法分析C語(yǔ)言描述(原書(shū)第2版)

    電子發(fā)燒友網(wǎng)站提供《數(shù)據(jù)結(jié)構(gòu)與算法分析C語(yǔ)言描述(原書(shū)第2版).txt》資料免費(fèi)下載
    發(fā)表于 12-17 14:13 ?0次下載

    比特幣瘋漲背后的四個(gè)原因以及是否存在騙局的分析

    比特幣的瘋漲造成了一種經(jīng)濟(jì)學(xué)困惑。數(shù)年內(nèi)超萬(wàn)倍的漲幅令人震驚錯(cuò)愕。
    的頭像 發(fā)表于 12-26 13:37 ?4293次閱讀

    數(shù)據(jù)結(jié)構(gòu)與算法分析C語(yǔ)言描述的電子教材詳細(xì)資料免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是數(shù)據(jù)結(jié)構(gòu)與算法分析C語(yǔ)言描述的電子教材詳細(xì)資料免費(fèi)下載
    發(fā)表于 08-09 17:36 ?0次下載

    數(shù)據(jù)結(jié)構(gòu)與算法分析C語(yǔ)言描述

    《數(shù)據(jù)結(jié)構(gòu)與算法分析C語(yǔ)言描述》曾被評(píng)為20世紀(jì)頂尖的30部計(jì)算機(jī)著作之一,作者在數(shù)據(jù)結(jié)構(gòu)和算法分析
    發(fā)表于 10-14 08:00 ?17次下載
    數(shù)據(jù)<b class='flag-5'>結(jié)構(gòu)</b>與算法<b class='flag-5'>分析</b>—<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>描述

    C語(yǔ)言會(huì)同意一些"令人震驚"的結(jié)構(gòu)

    這個(gè)代碼確實(shí)不咋符合習(xí)慣的寫(xiě)法,但是不管你相不相信,上面的例子是完全合乎語(yǔ)法的。問(wèn)題是編譯器如何處理它?
    的頭像 發(fā)表于 09-02 11:32 ?1459次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>會(huì)同意一些"<b class='flag-5'>令人震驚</b>"的<b class='flag-5'>結(jié)構(gòu)</b>

    你所想不到的十個(gè)關(guān)于大數(shù)據(jù)令人震驚的事實(shí)

    “大數(shù)據(jù)”這一術(shù)語(yǔ)的來(lái)源是有原因的,其規(guī)模確實(shí)非常大。但是,要掌握信息數(shù)字化的增長(zhǎng)并不容易。因此精心整理了有關(guān)當(dāng)今數(shù)據(jù)專(zhuān)家的這10個(gè)令人震驚的事實(shí),并展望了未來(lái)的趨勢(shì)。
    的頭像 發(fā)表于 09-10 15:31 ?3232次閱讀

    C語(yǔ)言的3種循環(huán)結(jié)構(gòu)分析

    C語(yǔ)言的循環(huán)結(jié)構(gòu)有for循環(huán)、while循環(huán)、do循環(huán)和goto循環(huán)。本文介紹前3種循環(huán)方式。 1. for循環(huán)結(jié)構(gòu) for循環(huán)也可以稱(chēng)為步進(jìn)循環(huán),它的特點(diǎn)是常用于已經(jīng)明確了循環(huán)的范圍
    的頭像 發(fā)表于 05-20 13:43 ?1.1w次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>的3種循環(huán)<b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>分析</b>

    令人震驚的特斯拉機(jī)器人!

    近日,特斯拉人形機(jī)器人亮相世界人工智能大會(huì),展現(xiàn)了全新的關(guān)節(jié)設(shè)計(jì)結(jié)構(gòu)。
    發(fā)表于 07-26 14:50 ?308次閱讀