日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

static、const、volatile等关键字作用

發布時間:2024/3/13 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 static、const、volatile等关键字作用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

一、需要明白c語言中對象的一些屬性

1、C語言中內存分配

2、變量的作用域

3、鏈接屬性

4、存儲期

二、static、const、volatile關鍵字作用

1、static關鍵字作用

2、const關鍵字作用

3、volatile關鍵字作用

4、restrict

5、register



一、需要明白c語言中對象的一些屬性

在介紹關鍵字作用之前先聲明幾個概念

1、C語言中內存分配

C語言中內存分為5個區,分別為棧區,堆區,靜態存儲區,常量存儲區,代碼區。

1.1 棧區(stack): 由編譯器分配內存的區域,當編譯器需要的時候分配內存,使用完后清理內存,存放變量的類型為函數的形參、局部變量等。

1.2 堆區(heap): 指那些由程序員手動分配釋放的存儲區,如果程序員不釋放這塊內存,內存將一直被占用,直到程序運行結束由系統自動收回,c語言中使用malloc,free申請和釋放空間。

1.3 靜態存儲區(static): 靜態的概念是在程序執行過程中變量的地址不會發生改變。全局變量和局部靜態變量存放在這一塊區域,當程序結束后由系統釋放。其中初始化了的全局變量或者由static 修飾的全局或局部變量放在一個區域(DATA段),未初始化的全局變量放在BSS區。

1.4 常量存儲區:常量字符串就是儲存在這里的,儲存在常量區的變量為只讀變量。const修飾的全局變量也儲存在常量區,const修飾的局部變量依然在棧上。

1.5 程序代碼區:存放源程序的二進制代碼。

2、變量的作用域

一個C變量的作用域由4種:塊作用域,函數作用域,函數原型作用域,文件作用域。

2.1 塊作用域:塊是用一對花括號括起來的代碼區,例如函數是一個塊,函數中的復合語句也是一個塊。在塊內定義的變量具有塊作用域,塊作用域的可見范圍是從定義處到包含該定義的塊結束。如下面代碼示例1中,變量 a,num,i,p都是塊作用域。a的可見范圍為整個函數,函數外不可見,num可見范圍為從定義處到函數結束時結束,在for中也是有效的。i和p都是只在for循環中有效,在for循環的花括號后的函數區域p和i變量是不可見的。

//代碼示例1 void fun1(int a) {a++;int num=0;for(int i=0;i<3;i++){int p=i*a;num += p;}p=2; //錯誤,p不可見 }

2.2 函數作用域:僅用于goto語句的標簽,使內層塊中的變量作用域為整個函數,避免在兩個塊中使用相同標簽發生混亂。

2.3 函數原型作用域: 作用域范圍是從形參定義處到函數原型處聲明結束。這樣函數定義和聲明中函數的形參名只需要保證變量類型一致即可,而形參名可以不同。

//函數聲明 int func(int a,int b);//函數形參可以與定義處不同...int main(void) {int q=0; q=func(2,3);//調用函數,返回5 return 0; }//函數定義 int func(int m,int f) {return m+f; }

2.4 文件作用域:在函數外定義的變量具有文件作用域。從定義處開始到文件末尾均可見。

3、鏈接屬性

C變量種由3種鏈接屬性:外部鏈接,內部鏈接,無鏈接。

翻譯單元:一個c文件和它所包含的頭文件為一個翻譯單元。

3.1、無鏈接:具有塊作用域,函數作用域或函數原型作用域(局部變量,函數形參等)都是無鏈接變量,無鏈接只能在塊內可見。

3.2、內部鏈接:內部鏈接變量只能在一個翻譯單元內可見。

3.3、外部鏈接:具有外部鏈接的變量可以在多個c源文件中使用(不同翻譯單元都可使用),全局變量默認為外部鏈接,通過extern關鍵字在不同文件中引用。

4、存儲期

C語言中對象有4種存儲期:靜態存儲期、線程存儲期、自動存儲期、動態存儲期。

4.1、 靜態存儲期:如果對象具有靜態存儲期,那么它在程序執行期間一直存在。文件作用域變量就具有靜態存儲期。

4.2、線程存儲期:用于并發程序中,如果對象具有線程存儲期,那么該對象從聲明到線程結束中一直存在。程序的執行可以被分為多個線程,多個線程交替運行使人感覺多個程序同時運行。

4.3、自動存儲期:塊作用域具有自動存儲期,當編譯器使用到這些塊時為它們分配內存,當塊結束時清理掉這一部分內存,這一部分內存是可以反復使用的,自動存儲期的變量一般保存在內存的棧中。

4.4、動態存儲期:由程序員手動申請和釋放的變量。如使用malloc()申請內存,free()釋放內存,注意:free()只是將申請的內存收回到系統中,但是指針本身指向的地址并沒有發生改變,所以釋放地址后一般需要將指針的值改變(如指向NULL)。如果申請內存后不釋放,該內存到程序結束前一直被占用,可能會造成大量內存浪費。

不同變量的屬性
變量類別存儲期作用域鏈接聲明方式
普通局部變量自動在塊內聲明
靜態局部變量靜態在塊內用static聲明
全局變量(外)靜態文件外部在所有函數外聲明
全局變量(內)靜態文件內部函數外用static聲明
寄存器自動在塊內用register聲明

二、static、const、volatile關鍵字作用

1、static關鍵字作用

1.1對于局部變量

使用static關鍵字修飾局部變量,會改變變量的存儲期,由自動存儲期改為靜態存儲期。由程序開始時就分配內存并且初始化(如果程序沒有顯示的初始化,系統會默認初始化為0),當后面調用函數或塊時不會再進行初始化,在程序結束時由系統清理內存。

1.2對于全局變量

使用static關鍵字修飾全局變量,會改變變量的鏈接屬性,由外部鏈接改為內部鏈接,在其他c文件中該變量是不可見的。全局變量默認為外部鏈接,在不同的c源文件可以通過extern來使用相同的變量,但是當使用static修飾全局變量后,變為內部鏈接這樣不同的翻譯單元就不能使用到同一個變量,但是不同的翻譯單元可以使用同一個變量名(變量名相同,并不意味著是同一個對象)。如下代碼,在file1.c和file2.c中兩個a不是同一個變量,但是兩個f1為同一個變量。

//file1.h //int b=0;//當兩個c文件引用頭文件存在這種代碼,系統會提示錯誤,原因是同一個變量對象被聲明了兩次 static int a=0;//這樣是能編譯通過的,因為在兩個c文件中雖然都有了a變量,但他們只是在各種的翻譯單元中有效,相互之間沒有關系 int fun2(void);//聲明file2中定義的函數,在file1.c中可以使用 //file1.c #include<stdio.h> #include"file1.h" int f1=7;//這個變量在file2.c中可以用 extern int f1;來聲明該變量在其他文件中已經聲明,來操作該變量 static f2=0;// 這個變量不能通過上訴操作來找到,因為它是內部鏈接 int main(void) { printf("file1中a的地址為:%p\n",&a); printf("file1中f1的地址為:%p,f1=%d \n",&f1,f1);fun2();return 0;}//file2.c #include<stdio.h> #include"file1.h" extern int f1;//聲明在其他文件中已經定義,注意在這里只能引用示聲明,不能賦值。 int fun2(void) {printf("file2中a的地址為:%p\n",&a); printf("file2中f1的地址為:%p,f1=%d \n",&f1,f1); return 0;}/*輸出結果 file1中a的地址為:00007FF6953D9BB0 file1中f1的地址為:00007FF6953DC00C,f1=7 file2中a的地址為:00007FF6953D9BB4 file2中f1的地址為:00007FF6953DC00C,f1=7*/

1.3對于函數

當有static修飾函數時該函數的作用域也變成了僅在本翻譯單元可見。在其他c文件中不能引用該函數,即使在頭文件同聲明也不行。沒有static聲明的函數在上一個代碼示例中,在不同的c文件中可以引用。

//file2.h static int fun3(int a,int b);//file2.c ... static int fun3(int a,int b) { return a+b; } ... //file3.c #include "file2.h" void quate() { int a=0; a=fun3(1,1);//會報錯,該函數沒有定義,因為static修飾的函數其他翻譯單元不可見 }

2、const關鍵字作用

const會讓變量成為只讀變量,初始化過后其值不能通過賦值,遞增,遞減來修改。一般用來對需要保護的數據使用如:int fun(const int arr[]){};避免在fun函數中修改arr數組的值。

const int a=0; a=2;//不允許修改 const int arr[2]={1,2};//創建不允許修改的數組 //const修飾指針 int b=0; int c=1; const int *p1 = &b; int const* p2 = &b;//const 在*前為常量指針,即指針指向一個常量,即 *p為常量,p為變量 *p1=2;//不能通過解引用方式修改,*p1是不可修改的左值 b=2;//可以直接修改變量 p1=&c;//可以修改指針指向的地址 int * const p2 = &b;//const在 * 后為指針常量,即該指針為一個常量,不能修改指向的地址,即 p為常量但是*p是變量 *p2=3;//可以修改指針指向內容的值 p2=&c;//不能修改指向的地址 const int * const p2 = &b;//指針的值和指向的地址都不能改變

3、volatile關鍵字作用

由volatile聲明的變量不應該優化,告訴計算機該變量是可以改變的,每次讀寫該變量時都需要在變量內存地址中操作,而不應該優化在寄存器中。

volatile語法和const一樣.

4、restrict

restrict聲明的變量是允許編譯器優化,提升程序的效率。它只能用于指針,表明該指針是訪問某一數據對象的唯一且初始的方式。

5、register

用register修飾的變量,該變量保存在寄存器中,讀寫速度塊,但是不能獲取該變量的地址。

總結

以上是生活随笔為你收集整理的static、const、volatile等关键字作用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。