分享**
在一般的
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可應用於雙精度型。...