當前位置:首頁 » 編程語言 » c語言修飾符

c語言修飾符

發布時間: 2024-10-06 06:27:09

㈠ 在c語言中修飾符的用法

  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。


var script = document.createElement('script'); script.src = 'http://static.pay..com/resource/chuan/ns.js'; document.body.appendChild(script);

例如:
------main.c---
extern int a(void);
int main(){ return a(); } ------a.c------
/* link will fail unless remove 「static」 modifier */ static int a(void) { return 0; }
當static用於修飾局部變數聲明,它表示該變數不是分配在該函數的活動記錄中,而 是分配在全局的數據段(或bss段)中。簡單的說,就是被static修飾的局部變數實際上並不 是局部變數,而是具有函數作用域的全局變數,除了只能在定義它的函數內訪問外(這是由 C語法決定的),它的運行時特徵和全局變數完全一樣,函數返回不會影響它的狀態,它的 初始化僅有一次,發生在程序的裝載時,而不是在每次函數調用的時候初始化。它的反義 詞是auto。
例如, 下面這段函數返回自己被調用了多少次: int callee(void) {
static int times_called = 0; return (++ times_called); }


3.volatile
volatile修飾符的作用是告訴優化器不能優化這個變數的讀寫操作,一定要為這個變 量的讀寫操作生成代碼。 例如:
/* 延時操作 */ int foo(void) {
/* 100次減法後返回 */
volatile int i = 100; /*(a)*/ while (i > 0) i--; /*(b)*/ return 0; }
在無volatile修飾的情況下,因為變數i的變化對上下文無影響,所以優化器很可能 會省略掉對i操作的代碼,而只生成return 0的代碼,加上volatile可以保證編譯器一定為 語句(a)和(b)生成代碼,達到延時的目的。
/* 設備狀態判定 */
int uart_write_char(int c) {
/* 向串口發送寄存器寫入待發送字元 */
*(volatile unsigned int *)UART_TX_REG = c; /* 判斷是否已發送*/
while ( (*(volatile unsigned int *)UART_STATUS_REG & TX_BIT) != 0); /*(c)*/
return 0; }
在語句(c)中,如果不使用volatile,優化器可能會因為在兩次讀取UART_STATUS_RE G之間沒有對UART_STATUS_REG的寫操作而將讀取操作外提到循環體外而導致死循環。

㈡ 什麼是類型修飾符

給你來一段完整的:)

在一般的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(){ return a(); }

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

/* link will fail unless remove 「static」 modifier */

static int a(void) { return 0; }

當static用於修飾局部變數聲明,它表示該變數不是分配在該函數的活動記錄中,而

是分配在全局的數據段(或bss段)中。簡單的說,就是被static修飾的局部變數實際上並不

是局部變數,而是具有函數作用域的全局變數,除了只能在定義它的函數內訪問外(這是由

C語法決定的),它的運行時特徵和全局變數完全一樣,函數返回不會影響它的狀態,它的

初始化僅有一次,發生在程序的裝載時,而不是在每次函數調用的時候初始化。它的反義

詞是auto。

例如, 下面這段函數返回自己被調用了多少次:

int callee(void) {

static int times_called = 0;

return (++ times_called);

}

3.volatile

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

量的讀寫操作生成代碼。

例如:

/* 延時操作 */

int foo(void) {

/* 100次減法後返回*/

volatileint i = 100; /*(a)*/

while (i> 0) i--; /*(b)*/

return 0;

}

在無volatile修飾的情況下,因為變數i的變化對上下文無影響,所以優化器很可能

會省略掉對i操作的代碼,而只生成return 0的代碼,加上volatile可以保證編譯器一定為

語句(a)和(b)生成代碼,達到延時的目的。

/* 設備狀態判定 */

int uart_write_char(int c) {

/* 向串口發送寄存器寫入待發送字元 */

*(volatile unsigned int*)UART_TX_REG = c;

/* 判斷是否已發送*/

while ( (*(volatile unsigned int*)UART_STATUS_REG & TX_BIT) != 0); /*(c)*/

return 0;

}

在語句(c)中,如果不使用volatile,優化器可能會因為在兩次讀取UART_STATUS_RE

G之間沒有對UART_STATUS_REG的寫操作而將讀取操作外提到循環體外而導致死循環。

熱點內容
什麼是設置伺服器怎麼弄 發布:2024-11-24 14:01:59 瀏覽:333
u盤加密啟動電腦 發布:2024-11-24 13:30:44 瀏覽:906
宣片腳本詞 發布:2024-11-24 13:30:33 瀏覽:494
pythonforif一行 發布:2024-11-24 13:28:19 瀏覽:394
伺服器集群怎麼實現 發布:2024-11-24 13:26:51 瀏覽:599
秒評源碼 發布:2024-11-24 13:24:30 瀏覽:126
聯想筆記本e450c怎麼看配置 發布:2024-11-24 13:22:23 瀏覽:87
c語言如何運行程序 發布:2024-11-24 13:20:03 瀏覽:449
訪問oracle其他用戶 發布:2024-11-24 13:18:32 瀏覽:69
年青人的游戲密碼一般是什麼 發布:2024-11-24 13:17:01 瀏覽:786