“#if 0/#if 1 … #endif”的注釋作用

來源:互聯網
上載者:User

1、先說“#if 0/#if 1 ... #endif”的作用,樓上諸位或多或少都說到了一點,但都沒有說到關鍵的地方。我們知道,C標準不提供C++裡的“//”這樣的單行風格注釋而只提供“/* */”這樣的塊注釋功能,我們通常使用它寫代碼中說明性的注釋文字(注釋作用)以及在調試時關閉某段代碼對編譯器的可見度(屏蔽作用),當然,這裡所謂的“注釋作用”和“屏蔽作用”是我們從功能上下的主觀定義,對前置處理器而言,兩者並無任何區別。對於前者,因為“注釋”中不會再出現“注釋”和“需要屏蔽的程式碼片段”,所以不會有嵌套的需求,所以通常不會有問題;而對於後者,當我們在偵錯工具時需要“屏蔽”某段代碼時,該段代碼中可能包含著前述的“注釋”和/或“已被屏蔽的程式碼片段”,這時就產生了“/*
*/”嵌套使用的需求,但SB的C標準恰恰不允許我們這麼幹。當你試圖使用嵌套的塊注釋功能時,會發現前置處理器把最外層注釋的開始和最內層注釋的結尾這兩者之間的內容處理成了注釋,而其後一直到最外層注釋結尾的內容被當作了“有效代碼”——這顯然會引起若干語法錯誤而導致編譯中止。高手們開動腦筋想到了“#if 0 ... #endif”,它同樣由前置處理器進行處理,同樣可以“屏蔽”一段代碼,你想把解說文字寫在裡面也可以,這些和“/* */”都一樣,但不一樣的是:第一它允許嵌套(層數上限由前置處理器決定)、第二你隨時可以把“#if
0”改成“#if 1”來取消對某段代碼的“屏蔽”——很卓越的特性,快拋棄笨拙的“/* */”吧!它唯一的缺點就是在編輯器中沒有“注釋”該有的文本顯示樣式。


2、現在再來說說2樓提到的自動變數局部化的問題:

------------------------------------------------

通過google,得知:

#if 0
code
#endif




(1)code中定義的是一些調試版本的代碼,此時code完全被編譯器忽略。如果想讓code生效,只需把#if 0改成#if 1 

(2)#if 0還有一個重要的用途就是用來當成注釋,如果你想要注釋的程式很長,這個時候#if 0是最好的,保證不會犯錯誤。(但是林銳的書上說千萬不要把#if 0 來當作塊注釋使用) 

#if 1可以讓其間的變數成為局部變數。 

(3)這個結構表示你先前寫好的code,現在用不上了,又不想刪除,就用這個方法,比注釋方便。 

------------------------------------------------


通過我上面說的第一點,我們可以知道,對“#if/#endif”的處理是前置處理器完成的,而前置處理器的唯一工作就是作“文字替換”的“預先處理”工作,它並不負責常數符號表的產生、變數儲存空間的分配、代碼的重定位等工作,那麼完全是給前置處理器看的“#if/#endif”怎麼能控制變數的生存期、怎麼能決定變數可以在哪裡定義??

開啟編輯器,寫下如下代碼:

===========================
volatile unsigned char a;
unsigned int main(void)
{
a = 0;
#if 1
unsigned char *p = &a;
*p = 255;
#endif
return 0;
}
===========================



存成.c檔案後用任何C編譯器(不包括C++編譯器)編譯,都會在紅字那一行報錯——為什麼呢?因為前置處理器進行“預先處理”的時候發現if的條件運算式為“真”,所以它把那段代碼塊留下了,而只把代碼塊前後的“預先處理指示符號(或者叫做預先處理命令)”給清除掉了,這樣,預先處理後的結果交給編譯器“翻譯”的時候,它發現在一個函數(在這裡為main函數)內部的運算式語句(在這裡是a = 0;)之後發現了變數聲明/定義語句(在這裡是聲明並定義指標變數p的語句)——按照編譯器的規則,這是一個錯誤,所以它拒絕接受這樣的輸入、罷工並開始抱怨(中止編譯、給出錯誤資訊)。


至此,關於“#if 1/#if 0/#endif”,我要說的就全說完了,歡迎大家拍磚哈~_~



下面再多囉嗦兩句。

--------------------------

那麼我們能不能享受C++程式員所得到的“將變數的定義放在它開始被需要的地方”這種待遇呢?

答案是肯定的。

手段?

——代碼塊!


  用一對大括弧括起來的代碼塊的首部,可以聲明/定義變數,這些變數的範圍僅限於該代碼塊內部,當然,這些變數聲明/定義語句也必須全部位於該代碼塊中第一個運算式語句之前,不然會出現上面描述的錯誤,不過好在C編譯器允許我們在代碼塊中嵌套定義代碼塊,所以大家從現在開始,大可不必在函數的開頭定義一大堆變數,那裡只要寫一些在整個函數執行過程當中都需要的變數的聲明/定義語句就好了;至於迴圈結構的迴圈變數等這些生存期不長的變數,它們的聲明/定義語句完全可以放在一個用一對大括弧括起來的代碼塊的首部。

  囉嗦了這麼多,寫一小段代碼證明一下我的說法,呵呵:

===========================
volatile unsigned char a;
unsigned int main(void)
{
a = 0;
{ //注
unsigned char *p = &a;
*p = 255;
}
return 0;
}
===========================



  註:我個人的代碼書寫風格是大括弧獨佔一行並且縮排量與父語句相同,函數體、迴圈體、case、if四者中的語句增加縮排,但如上的“代碼塊”則不增加。

存檔、編譯。

Hmmmm,編譯器不再在紅色的行給出錯誤提示了,編譯通過,得證~_~

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.