理解C語言中幾個常見修飾符

 

寫在前面

今天下午一個同事問「register」關鍵字是什麼作用?噢,你說的是「register」啊,它的作用是……腦袋突然斷片兒,我擦,啥意思來着,這麼熟悉的陌生感。做C語言開發時間也不短了,不過好像沒有用到過「register」,但作用還是知道的,一下子想不起來了,一萬個草泥馬飛奔過來。

其實C語言中除了register外,還包含常見的conststaticvolatileautoextern等修飾符,現在一起再總結一下好了。

register 修飾符

register,寄存器變量,告訴編譯器它所聲明的變量在程序中使用的頻率非常高,請編譯器儘量將此變量放在寄存器中,這樣程序執行速度更快。但實際上編譯器不一定這麼做,可以忽略此選項。

register 修飾符的幾點注意點:

  • 變量必須是 CPU 接受的類型,單個值,長度小於等於整數的長度
  • 只能使用於局部變量和函數形參,全局(register)變量是非法的
  • 無論寄存器變量是否存放在寄存器中,它地址都是不能訪問的(取&)
  • 其實過量的寄存器聲明並沒有什麼壞處,寄存器可以忽略

const 修飾符

const修飾普通變量

有時候我們希望定義一個變量,它的值在整個作用域都不能變,比如定義緩衝區大小等,可以用 const 來修飾。

// 定義常量 strlen
const int strlen = 4096;
// 試圖修改 strlen 變量,編譯器會報錯
strlen = 2048;

一般常量在定義時同時進行初始化,否則在定義完之後不能對其進行賦值操作,常見的初始化方式有:

const int num = get_num();  // 運行時初始化
const int num = n; // 運行時初始化
const int num = 10; // 編譯時初始化

const 變量真的就不能修改嗎?看個例子:

const int bufsize = 1024;
int *p = &bufsize;
*p = 2048;
printf("bufsize = %d\n", bufsize);

打印結果是2048。其實 const 修飾的變量不變的本質含義是程序中通過引用變量符號 bufsize 時不能夠進行修改,而不是 bufsize 變量所指向那段內存數據不能修改。

const修改指針變量

const 可以與指針變量一起使用,可以限制指針變量,也可以限制指針變量指向的內容。

const int *ptr;     // 指針指向內容不能修改
int const *ptr; // 與第1種等價
int* const ptr; // 指針ptr變量本身不能修改
const int* const ptr; // 指針變量和指針變量指向內容都不能修改

const修改函數參數

其實C語言中使用 const 定義常量並沒有什麼優勢,完全可以使用#define來替代。const 通常用在函數形參中,當形參是一個指針,爲了防止函數內部修改指針指向的內容時,就可以用 const 限制。


size_t strlen(const char *s);
int strcmp(const char *s1, const char *s2);

常見C語言標準庫中都有const限制,在我們自定義函數中也可以適當使用 const 來保證程序的健壯性。

const 類型與非 const 類型轉換

當一個指針類似const char *str1,表示str1指針指向內容不能修改;但如果將 str1 賦值給 str2,這時 str2 沒有通過 const 限制,通過 str2 就可以修改指針指向內容,這就失去了 const 的意義,編譯器是不提倡這麼做的。

const 與非 const 是兩種類型,將非 const 指針賦值給 const 指針,編譯器接受;如果將 const 指針賦值給非 const 指針,這樣將增加指針變量的權限,不安全,有可能發生寫入的危險。所以我們在寫程序時遵守,對指針類型儘可能加 const 修飾;不能將 const 指針賦值給 const 指針。

static 修飾符

static 修飾符在程序中使用最爲廣泛,它大概有如下幾種用法:

  • 修飾局部變量:增加了局部變量的生命週期,若定義未初始化,則默認初始化爲0
  • 修飾全局變量:縮小了全局變量的作用域,限制在本模塊(文件)中訪問
  • 修飾函數:縮小了函數的作用於,限制函數只能被本模塊調用

volatile 修飾符

關鍵字 volatile 感覺是和 register 有點相反的意思,表示變量隨時可能被修改,且系統對實時性要求很高,請一定從內存中讀取內容,不要直接拷貝寄存器中的數據,有可能數據老舊。常見的使用場合包括中斷服務程序和嵌入式系統的寄存器相關操作。

extern 修飾符

關鍵字 extern 常用在變量和函數聲明前,用來說明此變量或函數是在別處定義過的,要在此處引用。
在 hello.c 中:

void hello()
{
printf("Hello.\n");
}

在 main.c 文件中:

extern void hello();
hello(); // 聲明之後調用 hello 函數

在 main.c 文件被編譯時,告訴編譯器hello()在別的地方定義過了,這裏只是引用一下,放心編譯好了,在程序最後鏈接的時候會去找hello實際定義的函數。

auto 修飾符

關鍵字 auto 其實可以理解爲就是局部變量的顯示說明,程序中很少去顯示聲明某個變量爲 auto 的。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章