C語言中的const修飾符用於修飾一個變量是const屬性的。被C語言的const修飾的變量具備只讀屬性,而且不能被修改。html
const修飾的變量 != 常量,const修飾的變量雖然不能別修改,可是和常量仍是有本質的區別的。數組
在定義const類型的變量的時候,必須進行初始化,固然,在const做爲函數的參數的時候,是不須要初始化的。函數
編譯器一般不爲普通const 只讀變量分配存儲空間,而是將它們保存在符號表中,這使得它成爲一個編譯期間的值,沒有了存儲與讀內存的操做,使得它的效率也很高。優化
const 定義的只讀變量從彙編的角度來看,只是給出了對應的內存地址,而不是象#define同樣給出的是當即數,因此,const定義的只讀變量在程序運行過程當中只有一份拷貝(由於它是全局的只讀變量,存放在靜態區),而#define定義的宏常量在內存中有若干個拷貝。#define宏是在預編譯階段進行替換,而const修飾的只讀變量是在編譯的時候肯定其值。#define宏沒有類型,而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。線程
volatile 關鍵字和const 同樣是一種類型修飾符,用它修飾的變量表示能夠被某些編譯器未知的因素更改,好比操做系統、硬件或者其它線程等。遇到這個關鍵字聲明的變量,編譯器對訪問該變量的代碼就再也不進行優化,從而能夠提供對特殊地址的穩定訪問。code
柔性數組又稱爲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中,能夠直接在結構體中定義一個自由數組成員,自由數組的語法以下:
關於GCC對柔性數組的支持,能夠訪問這個網站:http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html#Zero-Length
對於這樣一個表達式:
a+++b
到底表示的是什麼呢?是a+ (++b)仍是(a++) +b?這個就須要考慮C語言在語法分析的時候是以什麼方式解析的。
在C語言的編譯器進行語法分析的時候,使用的是貪心法則。也就是說在處理表達式的時候,若是當前的字符能夠和前一個字符串組成一個有意義的符號,則繼續讀入下一個字符,直到沒法組成一個有意義的字符。
也就說對於上述的表達式,在解析到a+後碰到了+,這個時候,因爲a++在C語言中是合法的,那麼它繼續處理下一個+,因爲a+++在C語言中是非法的,那麼就不把+做爲表達式的一部分,也就說上述的表達式就被解析爲:(a++) + b。
在編譯的時候可使用的一些指令,用於在編譯的時候輸出一些有用的信息,便於追蹤編譯過程,以及控制編譯。
#line //改變當前的行數和文件名稱,基本語法以下:#line number["filename"] #error //編譯程序時,若是遇到#error就會產生一個編譯錯誤提示信息,並中止編譯。
編譯器在編譯過程預約義了一些宏,用於輸出一些編譯過程的信息:
_LINE_ //編譯器正在編譯的行號 _FILE_ //編譯器正在變異的文件名 _TIME_ //編譯的時間 _STDC_ //判斷該文件是否是定義成標準C程序
參考:《C語言深度剖析》