<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          [收藏] 宏工作原理以及典型面試10問(wèn)

          共 1696字,需瀏覽 4分鐘

           ·

          2020-09-06 11:46

          [導(dǎo)讀] C語(yǔ)言中宏是非常有價(jià)值的語(yǔ)言特性之一,也是面試中必考察的要點(diǎn)之一,本文來(lái)分享總結(jié)一些關(guān)于宏的常見(jiàn)面試問(wèn)題。希望能幫助到有需要的小伙伴們。

          宏工作原理

          以hello word程序?yàn)槔齺?lái)看看,將下述代碼存成hello.c

          #include?
          #define?STR?"hello?world"
          /*這是一個(gè)hello?word程序*/
          int?main(void)
          {
          ????printf("%s",STR);
          ????return?0;
          }

          為了說(shuō)明問(wèn)題,這里用下面的命令進(jìn)行顯式預(yù)處理,將得到hello.i文件,實(shí)際編譯過(guò)程中,會(huì)自動(dòng)完成。

          //gcc?-E?生成預(yù)處理文件
          gcc?-E?hello.c?-o?hello.i

          來(lái)大致看看hello.i文件

          #?1?"hello.c"
          #?1?""
          #?1?""
          #?1?"/usr/include/stdc-predef.h"?1?3?4
          #刪除很多行
          .......
          extern?char?*ctermid?(char?*__s)?__attribute__?((__nothrow__?,?__leaf__));
          #?912?"/usr/include/stdio.h"?3?4
          extern?void?flockfile?(FILE?*__stream)?__attribute__?((__nothrow__?,?__leaf__));

          extern?int?ftrylockfile?(FILE?*__stream)?__attribute__?((__nothrow__?,?__leaf__))?;

          extern?void?funlockfile?(FILE?*__stream)?__attribute__?((__nothrow__?,?__leaf__));
          #?942?"/usr/include/stdio.h"?3?4

          #?2?"hello.c"?2
          #?4?"hello.c"
          int?main(void)
          {
          ????printf("%s","hello?world");
          ????return?0;
          }

          上面這步操作做了三件事情:

          • 刪除注釋:刪除所有注釋。注釋僅供程序員理解代碼,注釋對(duì)機(jī)器沒(méi)有用。因此預(yù)處理器在預(yù)處理過(guò)程中會(huì)刪除注釋,因?yàn)樽⑨屧趫?zhí)行過(guò)程中是不需要的,也不會(huì)被執(zhí)行。所以注釋盡管寫不影響程序的邏輯,當(dāng)然寫的過(guò)也未必是好事,過(guò)少也不是好事。個(gè)人理解一份好的代碼應(yīng)盡量少注釋,應(yīng)該通過(guò)合理的命名習(xí)慣,良好的編程風(fēng)格來(lái)提高可讀性,在一些關(guān)鍵復(fù)雜算法處則應(yīng)清晰的加上注釋。在hello.c中的注釋 ?/*這是一個(gè)hello word程序*/ ?在預(yù)處理后被刪除掉了。

          • 文件包含:包含程序需要的所有文件。C語(yǔ)言中使用#include,這是預(yù)處理器的指令,告訴預(yù)處理器包含指定文件的內(nèi)容。例如#include將告訴預(yù)處理器將stdio.h中所有的內(nèi)容包含進(jìn)來(lái)。也可以使用雙引號(hào)-#include “stdio.h” 注意:如果使用尖括號(hào),則在編譯器包含路徑中搜索文件。如果文件名用雙引號(hào)包起來(lái),則搜索路徑將擴(kuò)展為除了編譯器包含路徑外的當(dāng)前目錄下。

          • 宏展開(kāi)替換:比如上例中宏STR在預(yù)處理時(shí)就被展開(kāi)替換了。宏有兩種常見(jiàn)形式:

            大致說(shuō)明了宏的工作原理,來(lái)看看一些常見(jiàn)的面試問(wèn)題:

            • 不帶參形式(有的地方也稱對(duì)象形式object-like)。

              #define?PI?3.1415926f
            • 帶參形式(有的地方也稱為函數(shù)形式function-like)。

              #define?SQUARE(x)?((x)*(x))

          面試問(wèn)題1

          如下代碼,問(wèn)有多少個(gè)"嵌入式客棧"會(huì)被打???

          (A) ?1?

          (B) ?3?

          (C) ?4?

          (D) 編譯錯(cuò)誤

          #include??
          #define?PRINT_HELLO(i,?times)?do?\?
          ???????{?\?
          ?????????if?(i++?times)?\?
          ?????????{?\?
          ???????????printf("嵌入式客棧\n");?\?
          ???????????continue;?\?
          ???????????}?\?
          ???????}while(1)?
          ??
          int?main()?
          {?
          ????PRINT_HELLO(0,?3);?
          ????return?0;?
          }?

          答案:D

          解析:PRINT_HELLO宏在預(yù)處理器時(shí)被擴(kuò)展。宏展開(kāi)后,if表達(dá)式變?yōu)椋篿f(0 ++ <3)。0是一個(gè)常數(shù),常數(shù)如何自增呢?,因此應(yīng)用增量運(yùn)算符會(huì)產(chǎn)生編譯時(shí)錯(cuò)誤。

          面試問(wèn)題2

          下述代碼的輸出是什么?

          (A) 3

          (B) 5?

          (C) 3 或者 5 取決于X的值?

          (D) 編譯錯(cuò)誤

          #include??
          #if?A?==?3?
          ????#define?B?3?
          #else?
          ????#define?B?5?
          #endif?
          ??
          int?main()?
          {?
          ????printf("%d",?B);?
          ????return?0;?
          }?

          答案:B

          解析:乍一看,輸出似乎是編譯時(shí)錯(cuò)誤,因?yàn)樯形炊x宏A,所以A是不等于3的,所以會(huì)將B定義為5。你如不信,也可以用上面的辦法gcc -E hello.c -o hello.i來(lái)驗(yàn)證,或者編譯運(yùn)行一遍。

          面試問(wèn)題3

          問(wèn):針對(duì)下述代碼,哪個(gè)答案正確?

          (A) 嵌入式

          (B) 客棧?

          (C) 編譯錯(cuò)誤

          (D) 運(yùn)行錯(cuò)誤

          #include??
          #define?X?3?
          #if?!X?
          ????printf("嵌入式");?
          #else?
          ????printf("客棧");????
          #endif?
          int?main()?
          {?
          ????return?0;?
          }

          答案:C 編譯錯(cuò)誤

          解析:程序編譯三部曲:預(yù)處理、匯編、鏈接,那么在預(yù)處理時(shí),上述代碼就變成下面這樣:

          #這里還有stdio.h的包含內(nèi)容
          printf("客棧");?
          int?main()
          {
          ????return?0;
          }

          printf在main外面被調(diào)用了,所以編譯會(huì)出錯(cuò)。

          面試問(wèn)題4

          下述代碼的輸出應(yīng)該是?

          (A) 嵌入式?

          (B) 客棧

          (C) 嵌入式 或 客棧

          (D) 編譯錯(cuò)誤

          #include??
          #define?IS_EQUAL(X,?Y)?X?==?Y?
          int?main()?
          {?
          ????#if?IS_EQUAL(X,?0)?
          ????????printf("嵌入式");?
          ????#else?
          ????????printf("客棧");?
          ????#endif?
          ????return?0;?
          }?

          答案:A

          解析:條件宏#if IS_EQUAL(X,0)擴(kuò)展為#if X ==0。預(yù)處理結(jié)束后,所有未定義的宏均使用默認(rèn)值0初始化。

          面試問(wèn)題5

          下述代碼的輸出應(yīng)該是?

          (A) 20?

          (B) 2000?

          (C) 0

          (D) 編譯錯(cuò)誤

          #include??
          #define?SQUARE(x)?x*x?
          int?main()?
          {?
          ??int?x;?
          ??x?=?2000/SQUARE(10);?
          ??printf("%d",?x);?
          ??return?0;?
          }?

          答案:B

          解析:預(yù)處理器用10*10替換SQUARE(10),表達(dá)式變?yōu)?x = 2000/10 * 10,x的值計(jì)算為2000。如前所說(shuō),應(yīng)定義如下:

          #define?SQUARE(x)?((x)*(x))

          面試問(wèn)題6

          下述代碼的輸出應(yīng)該是?

          (A) 編譯錯(cuò)誤

          (B) %s Embedded Inn?

          (C) Embedded Inn?

          (D) %s Embedded Inn Embedded Inn

          #?include??
          #?define?scanf??"%s?Embedded?Inn?"?
          int?main()?
          {?
          ???printf(scanf,?scanf);?
          ???return?0;?
          }?

          答案:D

          解析:在編譯的預(yù)處理階段之后,printf語(yǔ)句將變?yōu)椤?/p>

          printf(“%s?Embedded?Inn”,“%s?Embedded?Inn”);

          面試問(wèn)題7

          下述代碼的輸出應(yīng)該是?

          (A) 編譯錯(cuò)誤

          (B) 嵌入式客棧?

          (C) 客??蜅?/p>

          (D) 嵌入式嵌入式

          #include??
          #define?STR?"嵌入式"?
          int?main()?
          {?
          ??printf("%s",STR);?
          ??
          ??#define?STR?"客棧"?
          ??
          ??printf("%s",STR);
          ??return?0;?
          }

          答案:B

          解析:如果重新定義預(yù)處理程序指令,則預(yù)處理器不會(huì)給出任何錯(cuò)誤,它可能會(huì)發(fā)出警告。預(yù)處理器在使用之前獲取新值,并將其替換。

          面試問(wèn)題8

          下述代碼的輸出應(yīng)該是?

          (A) 100?

          (B) 編譯錯(cuò)誤?

          (C) 0?

          (D) 1

          #include??
          #define?ADHESION(x,y)?x##y??
          int?main()??
          {??
          ???int?var1?=?100;??
          ???printf("%d",?ADHESION(var,1));??
          ???return?0;??
          }?

          答案:A

          解析:運(yùn)算符##稱為“令牌粘貼(Token-Pasting)”或“合并(Merge)”運(yùn)算符。它將兩個(gè)符合合并為一個(gè)。因此在預(yù)處理之后,printf變?yōu)椤?/p>

          printf("%d",?var1);?

          面試問(wèn)題9

          下述代碼的輸出應(yīng)該是?

          (A) 6666.6

          (B) 666.6?

          (C) 編譯錯(cuò)誤

          (D) 無(wú)效值

          #include??
          #define?MAX?6666.6f
          int?main()?
          {?
          ???float?MAX?=?666.6;?
          ???printf("%f?",?MAX);?
          ???return?0;?
          }?

          答案:C

          解析:展開(kāi)一看便知。

          int?main()
          {
          ???float?6666.6?=?666.6;??//常數(shù)不可為左值
          ???printf("%d?",?6666.6);
          ???return?0;
          }?

          面試問(wèn)題10

          下述代碼的輸出應(yīng)該是?

          (A) 編譯錯(cuò)誤?

          (B) 嵌入式客棧

          (C) MAIN

          (D) main

          #include??
          #define?macro(n,?a,?i,?m)?m##a##i##n?
          #define?MAIN?macro(n,?a,?i,?m)?
          ??
          int?MAIN()?
          {?
          ????printf("嵌入式客棧");?
          ????return?0;?
          }

          答案:B

          解析:不注意可能會(huì)選A,認(rèn)為將MAIN敲成大寫了,其實(shí)仔細(xì)一看,通過(guò)前面兩個(gè)宏以及粘連操作符##將MAIN替換成main,所以沒(méi)有問(wèn)題,這個(gè)題目比較騷,主要考察細(xì)心以及粘連操作符。

          總結(jié)一下

          面試小提示:實(shí)際筆試中,只有掌握了宏的基本操作原理,以及宏預(yù)處理的本質(zhì),在解題時(shí)細(xì)心展開(kāi),一般而言不會(huì)有什么問(wèn)題。

          本文總結(jié)了宏的基本工作原理,以及10個(gè)比較典型的面試問(wèn)題,相信對(duì)于宏理解不深的盆友會(huì)有些許幫助。

          如喜歡請(qǐng)點(diǎn)贊/在看/分享支持!

          瀏覽 53
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品123视频 | 在线免费看逼视频 | AV2014天堂 | 超碰女人| 日本欧美一级色情片免费观看 |