C語言拾遺

1. 沒C++那麼噁心的const

 

C語言中的const修飾符用於修飾一個變量是const屬性的。被C語言的const修飾的變量具備只讀屬性,而且不能被修改。html

const修飾的變量 != 常量,const修飾的變量雖然不能別修改,可是和常量仍是有本質的區別的。數組

在定義const類型的變量的時候,必須進行初始化,固然,在const做爲函數的參數的時候,是不須要初始化的。函數

1.1編譯器對const變量的優化:

 

編譯器一般不爲普通const 只讀變量分配存儲空間,而是將它們保存在符號表中,這使得它成爲一個編譯期間的值,沒有了存儲與讀內存的操做,使得它的效率也很高。優化

const 定義的只讀變量從彙編的角度來看,只是給出了對應的內存地址,而不是象#define同樣給出的是當即數,因此,const定義的只讀變量在程序運行過程當中只有一份拷貝(由於它是全局的只讀變量,存放在靜態區),而#define定義的宏常量在內存中有若干個拷貝。#define宏是在預編譯階段進行替換,而const修飾的只讀變量是在編譯的時候肯定其值。#define宏沒有類型,而const修飾的只讀變量具備特定的類型。網站

1.2當typedef碰到變量修飾符(const)

 

typedef struct student
{
    /*code*/
}Stu_st,*Stu_pst;

1)const Stu_pst stu3;
2)Stu_pst const stu4;

 

對於定義的stu3 和stu4,它們的類型同樣嗎?答案是同樣的。爲何?this

在這裏咱們不能想固然的認爲typedef和#define同樣,直接進行展開。實際上,由於const修飾的都是變量自身,const對變量進行修飾的時候,不考慮類型,也就是說1)和2)中的typedef類型都被認爲是一個類型,而不是被展開。因此上述就至關因而:spa

const type var
      type const var操作系統

也就是說,const修飾的是變量var。線程

2. 很少見的volatile

 

volatile 關鍵字和const 同樣是一種類型修飾符,用它修飾的變量表示能夠被某些編譯器未知的因素更改,好比操做系統、硬件或者其它線程等。遇到這個關鍵字聲明的變量,編譯器對訪問該變量的代碼就再也不進行優化,從而能夠提供對特殊地址的穩定訪問。code

 

3. 結構體

 

3.1 柔性數組

柔性數組又稱爲0長數組(zero-length arrays),這是C99加進去的一個特性。能夠這樣定義一個柔性數組:

struct line {
       int length;
       char contents[];
};
     
struct line *thisline = (struct line *) malloc (sizeof (struct line) + this_length);
thisline->length = this_length;

在ISO C90中,在定義一個相似於柔性數組(在C90標準中尚未柔性數組的概念)的結構體成員的時候,contents[]在定義的時候須要定義成這樣:contents[0],其中的0是必須的。

在ISO C99中,能夠直接在結構體中定義一個自由數組成員,自由數組的語法以下:

  • 自由數組成員的長度爲0,在定義一個數組的個數的時候,[]中的0不被包括。
  • 自由數組成員是不徹底類型,因此對結構體使用sizeof操做符時不會包括自由數組成員的大小
  • 在一個自由數組前必須定義至少一個成員,不能在一個結構體中只定義一個自由數組。
  • 一個結構體若是包含了一個自由數組,或者在一個聯合中包含了這種結構體,那麼這種結構體或者聯合不能成爲結構體的成員或者是一個數組的成員。

關於GCC對柔性數組的支持,能夠訪問這個網站:http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html#Zero-Length

 

4. 在解析表達式時的貪心法則

 

對於這樣一個表達式:

a+++b

到底表示的是什麼呢?是a+ (++b)仍是(a++) +b?這個就須要考慮C語言在語法分析的時候是以什麼方式解析的。

在C語言的編譯器進行語法分析的時候,使用的是貪心法則。也就是說在處理表達式的時候,若是當前的字符能夠和前一個字符串組成一個有意義的符號,則繼續讀入下一個字符,直到沒法組成一個有意義的字符。

也就說對於上述的表達式,在解析到a+後碰到了+,這個時候,因爲a++在C語言中是合法的,那麼它繼續處理下一個+,因爲a+++在C語言中是非法的,那麼就不把+做爲表達式的一部分,也就說上述的表達式就被解析爲:(a++) + b。

 

5. 預處理

 

在編譯的時候可使用的一些指令,用於在編譯的時候輸出一些有用的信息,便於追蹤編譯過程,以及控制編譯。

#line    //改變當前的行數和文件名稱,基本語法以下:#line number["filename"]

#error   //編譯程序時,若是遇到#error就會產生一個編譯錯誤提示信息,並中止編譯。

 

編譯器在編譯過程預約義了一些宏,用於輸出一些編譯過程的信息:

_LINE_        //編譯器正在編譯的行號
_FILE_           //編譯器正在變異的文件名
_TIME_           //編譯的時間
_STDC_        //判斷該文件是否是定義成標準C程序

 

 


參考:《C語言深度剖析》

相關文章
相關標籤/搜索