關於C語言的型別修飾符

2022-08-16 19:36:12 字數 3278 閱讀 8110

分享**

在一般的

c教科書中,可以見到

6種型別修飾符,分別是

: auto, const, register,  

static, volatile, extern. 

區域性變數除非顯式指明為

static, 

否則預設為

auto

,所以一般不會在**中使用型別

修飾符auto. 

在後編譯器時代,優化器可以合理的分配暫存器,所以一般不會在**中使用型別修

飾符register. 

extern

只用於宣告全域性變數,用法單一。

本節將主要介紹

const, static

和volatile. 

1. const 

首先需要注意的是,

const

修飾的是在它前面的型別,如果它前面沒有型別,那它修

飾的是緊跟著它的那個型別。

例如:(a)const int i = 0; 

和(b)int const i = 0; 

是完全一樣的。

在(a)

中,const

前面沒有型別,它就修飾它後面的那個

int型別。在

(b)中,

const

修飾它前

面的int

型別,兩者沒有任何區別。

再看另乙個稍複雜一點的例子,下面兩條語句卻不相同:

(c)const int *pi = 0; 

/* 相當於

int const *pi = 0; pi

是乙個指向

const int

的指標,復引用此運算子為得到一

個const int

的型別,該型別不能作為左值,在該語句後使用類似於

*pi = 1

的操作將導致

編譯錯誤。但該變數本身並不具備

const

屬性,可以使用

pi = &i

的操作。可用於訪問唯讀

儲存器。

*/  

(d)int* const pi = 0; 

/* pi

是乙個指向

int型別的

const

指標,復引用此運算子為得到乙個

int型別,該型別可以

作為左值,在該語句可以使用類似於

*pi = 1

的操作,但該變數本身具備

const

屬性,使用

pi = &i

的操作將導致編譯錯誤。可用於訪問固定位置的儲存器。

*/ 再看乙個更複雜的例子:

(e)const int* const pi = 0; 

/* pi

和*pi

均不能作為左值。它只適合於讀取某個固定位置的唯讀儲存器

*/ const

還有下列典型用法

: * 

用於引數列表,通常修飾的是指標型別,表明該函式不會試圖對傳入的位址進行寫

操作。例如:

void *memcpy(void *, const void *, size_t); 

* 用於返回值,通常是乙個指向唯讀區域的指標。例如:

const datatype_t *get_fixed_item(int index); 

* 給固定不變的資料

(例如碼表

)加上唯讀屬性,在某些情況下可以減小

ram的開銷。

2.static 

static

用於全域性變數宣告和區域性變數宣告具有完全不同的語義,不得不說,這是c語

言設計中的乙個不合理之處。當

static

用於修飾全域性變數宣告

(或函式宣告,可以認為函式

宣告就是宣告乙個指向**段的指標,該指標的值最後由鏈結時決定,從這個意義上說,

函式宣告也是一種全域性變數宣告

),它表示該變數具有檔案作用域,只能被該原始檔的**

引用,不能被其他原始檔中的**訪問。在編譯時引起的實際變化是被

static

修飾的變數

不會被寫入目標檔案的輸出節,在鏈結時解析其他模組中的未定義符號時不會被引用到。

它的反義詞是

extern

。例如:

------main.c--- 

extern int a(void); 

int main() 

------a.c------ 

/* link will fail unless remove 

「static

」modifier */ 

static int a(void)  

當static

用於修飾區域性變數宣告,它表示該變數不是分配在該函式的活動記錄中,而

是分配在全域性的資料段(或

bss段

)中。簡單的說,就是被

static

修飾的區域性變數實際上並不

是區域性變數,而是具有函式作用域的全域性變數,除了只能在定義它的函式內訪問外

(這是由

c語法決定的

),它的執行時特徵和全域性變數完全一樣,函式返回不會影響它的狀態,它的

初始化僅有一次,發生在程式的裝載時,而不是在每次函式呼叫的時候初始化。它的反義

詞是auto。例如

, 下面這段函式返回自己被呼叫了多少次:

int callee(void)  

3.volatile 

volatile

修飾符的作用是告訴優化器不能優化這個變數的讀寫操作,一定要為這個變

量的讀寫操作生成**。

例如:/* 

延時操作

*/ int foo(void)  

在無volatile

修飾的情況下,因為變數

i的變化對上下文無影響,所以優化器很可能

會省略掉對

i操作的**,而只生成

return 0

的**,加上

volatile

可以保證編譯器一定為

語句(a)

和(b)

生成**,達到延時的目的。

/* 裝置狀態判定

*/ int uart_write_char(int c)  

在語句(c)

中,如果不使用

volatile

,優化器可能會因為在兩次讀取

uart_status_re 

g之間沒有對

uart_status_reg

的寫操作而將讀取操作外提到迴圈體外而導致死迴圈。

C 型別修飾符

資料隱藏是物件導向程式設計的乙個重要特點,它防止函式直接訪問類型別的內部成員。類成員的訪問限制是通過在類主體內部對各個區域標記public private protected來指定的。關鍵字 public private protected 稱為訪問說明符。乙個類可以有多個 public prote...

C 修飾符型別

c 允許在char int 和 double資料型別前放置修飾符。修飾符用於改變基本型別的含義,所以它更能滿足各種情境的需求。下面列出了資料型別修飾符 為了理解 c 解釋有符號整數和無符號整數修飾符之間的差別,我們來執行一下下面這個短程式 include using namespace std 這個...

C 修飾符型別

c 允許在char int 和 double資料型別前放置修飾符。修飾符用於改變基本型別的含義,所以它更能滿足各種情境的需求。下面列出了資料型別修飾符 修飾符signed unsigned long 和 short可應用於整型,signed和unsigned可應用於字元型,long可應用於雙精度型。...