前戲
要理解乙個c 程式,僅僅理解組成該程式的符號是不夠的,我們還需要理解這些符號是如何組成宣告、表示式、語句和程式的。今天我們就來討論一下不一樣的語法結構。
1. 正確理解函式宣告
你是否見過這樣的**「((void()())0)();」,你能知道這是上面意思嗎?
看不懂不用擔心,下面我們來分析一下:任何c變數的宣告都由兩部分組成:型別以及一組類似表示式的宣告符(declarator)。宣告符從表面上看魚表發揮有些類似,對他就只應該返回乙個宣告給定的結果。(void ()()0)是將常數0 轉型為「指向返回值為void 的函式的指標」型別。而((void(*)())0)();就可以看成是乙個函式呼叫,末尾的分號使得表示式成為乙個語句。當然我們也可以使用typedef來世表示式更加清晰:
typedef void (*funcptr)();
(*(funcptr)0)();
2. 運算子的優先順序問題在 c語言中,運算子優先順序有15個之多,如果不知道運算子的優先順序我們在處理問題,分析**時,就非常被動,那麼我們可以對運算子進行簡單的分組,了解各組運算子之間的相對優先順序,那麼記起來就相對簡單了,可以簡單的記做:!> 算術運算子 > 關係運算子》&&>|| > 賦值運算子。
語句結束符的分號問題
c語言以分號「;」,作為語句結束的標誌,那麼如果在表示式後多寫了分號,會出現什麼結果呢?這個分號也許會被視作乙個不會產生任何實際效果的空語句,或者編譯器會因為這個多餘的分號產生一條警告資訊,可以根據警告資訊去掉這個分號。但乙個例外就是在if 或者while語句之後多寫乙個分號,此時原來在if或者while之後的語句即使一條單獨的語句,魚條件判斷沒有了任何關係。請看一下**:
if(x > y)return;
if(x > y);return;
這兩句完全是不一樣的
4. switch 語句問題
c語言中的switch,在case分支後都需要新增乙個break;語句,不然會已知順著語句執行下去,達不到我們需要的效果。
5. 函式呼叫
與其他程式語言不同,c語言要求:在函式呼叫時及時函式不帶引數,也應該包含引數列表,因此,如果f 是乙個函式,f();乙個函式呼叫,而f;卻是乙個什麼也不做的語句。
6. else 懸掛問題
我們經常聽到說else要和if 配對使用,然而在我們寫**時,還是會經常出錯,例如如下**:
這段**的本意是分為兩種情況,x 等於0 不等於0,然而上面的**表達的意思卻截然不同。即 想不等於0,程式不做處理,x 等於0時,判斷y的值,做出不同的處理。
組織敏捷轉型常見的六大誤解,你知道幾個?
組織會出於多種原因而採用敏捷方法。一些組織希望能提高生產率和縮短產品上市時間,另一些組織希望能夠獲得更成功的產品,還有一些組織希望能增強開發人員與業務人員間的協作,以提公升質量或提高團隊成員的工作滿意度。當然,還有許多組織採用敏捷是希望能同時實現這些好處的組合。但是,為了能從敏捷中盡可能多地獲得好處...
你不得不知道的六大自動化測試技巧
測試自動化有助於提高開發速度,同時減少成本和工作量。在本文中,將分享如何進行自動化測試,以幫助保持測試自動化活動在正確的軌道上,以及測試執行 設計和維護大型企業應用程式的關鍵技巧。每個自動化測試專案都有其自身的特定需求。正確的工具可以顯著減少測試時間並提高測試團隊的效率。錯誤的工具會引入不必要的複雜...
C語言中const和指標的秘密你知道嗎
目錄 將乙個型別為 char 的值賦值給乙個 const char 型別的物件是否合法呢?先說結果,在vs的環境下,編譯器不會報錯也不會有任何程式設計客棧警告。但在linux環境下用gcc編譯就會出現下面的警告 warning assignment from incompatible pointer...