神奇的C語言,這纔是C語言大牛操做,做爲面試題,怕是秒殺衆人

固然下面列出來的幾點都是C的基礎用法,只不過是這些用法可能平時不會被注意。因此不少東西第一次看到的時候,可能會以爲很怪異,可是細細想一想就能很好的理解,也就能更好的清楚C語言的一些特性。可是在具體的編碼過程中,我仍是但願都能老老實實規規矩矩的。由於程序員不須要太多棱角,把代碼寫得規範整潔比耍小聰明要重要得多。下面我列舉了5個例子說明一些問題,若是你是老手看到這些就一笑而過吧,若是是新手,我相信仍是會獲得一些啓發的。程序員

1. #和##在宏中的做用,以及帶參宏,參數的傳遞問題。數組

2. 結構體中域的偏移位置的計算問題。微信

3. 結構體的定義以及初始化的用法。函數

4. 數組和指針在運算中的等價關係。學習

5. 數組在棧中的「變異」。測試

1. 例子:優化

說明:編碼

A) 預編譯中#是將右邊的參數轉成一個字符串,##是將左右兩邊的參數鏈接成一個字符串。例子是#的用法。3d

B) 宏當中的參數實際上是以逗號(,)分隔的,其餘的字符其實都被當作同一個參數,可是換行和空白其實被處理過了,使參數在同一個行中。有興趣的本身多作些測試吧,這個用法能夠用於要寫包含特殊字符的字符串,省得要寫不少的轉義字符(),可是中間不能有逗號,呵呵~指針

2. 例子:

說明:

A) &((struct _st*)0)->b 的做用是輸出_st結構體中b的偏移。爲何用0當成指針呢,其實很好理解:若是一個_st結構體的地址是0,那麼b的地址其實就是b在結構體中的偏移。

B) 其實按理,若是先作((struct _st*)0)->b運算,那麼程序確定異常,因此編譯器仍是作了優化的,具體編譯器怎麼作的,我也沒深究。

3. 例子:

說明:

A) 在結構體的初始化時,能夠指定域進行初始化,如例子中的.c = 1,順序能夠顛倒,這樣作的好處就是可讀性較強,對於大結構的初始化,在閱讀時很方便。缺點就是低版本的編譯器可能不支持。

B) 在結構體的聲明中,能夠指定域的大小,如例子中的int a : 1; 說明a只暫用一個bit,充分展現了C對二進制處理反面的親和力。

C) 爲何s.c輸出是-1,而不是1,其實很簡單,由於0xFFFFFFFF表示的是-1,那麼一個1bit大小的變量,全部位上面都是1,那麼它也表示-1。因此編碼的過程當中,有符號和無符號混用實際上是很危險的一件事情。

4. 例子:

說明:

A) 0[a] = 'x';是什麼玩意兒?若是寫成a[0]='x';其實你就明白是什麼意思了,可是說白了,a[0]和0[a]在編譯器看來是同樣的。由於數組在作[]運行時,實際上是作指針的加法運行:a[0]等價於*(a+0)。因此0[a]也就等價於*(0+a)是徹底正確的。

5. 例子:

說明:

A) 爲何兩行的結果會不同?在通常狀況下,按個人理解,一個數組a,&a和&a[0]的值是同樣的。可是當a在形參當中時就不同了。例子中,func函數中的a,其實a變量是在func函數的棧當中,在func內部,a其實已經被轉化成char *a,因此&a是表示指針變量a在棧中的地址,而&a[0]表示的是指針指向的內存空間的第一個元素的地址,其實也就是調用者傳入的數組的第一個元素的地址。不知道我說明白了沒有!!

B) 這個可能比較難理解,關鍵是明白一點,在數組做爲形參時,是被轉換成指針看待的。

我有一個微信公衆號,常常會分享一些C語言/C++技術相關的乾貨;若是你喜歡個人分享,能夠用微信搜索「C語言學習部落」關注

歡迎你們加入千人交流答疑裙:627+012+464

相關文章
相關標籤/搜索