1. 程式人生 > >對C語言 static作用——修飾 變數(全域性變數/區域性變數)、函式

對C語言 static作用——修飾 變數(全域性變數/區域性變數)、函式

*******************************概念********************************************
*******************************************************************************
首先得明白全域性變數、靜態全域性變數、區域性變數、靜態區域性變數的概念,下面進行舉例:
//main.c檔案中
int a = 0; //全域性變數
static int b=0;//靜態全域性變數
main() 
{ 
int c; //區域性變數
static int d;//靜態區域性變數 
}
  • 全域性變數:具有全域性作用域,全域性變數只需在一個原始檔中定義,就可以作用於所有的原始檔。
  • 靜態全域性變數:具有全域性作用域,它與全域性變數的區別在於如果程式包含多個檔案的話,它作用於定義它的檔案裡,不能作用到其它檔案裡,即被 static 關鍵字修飾過的變數具有檔案作用域。
  • 區域性變數:具有區域性作用域,它是自動物件(auto),它在程式執行期間不是一直存在,而是隻在函式執行期間存在,函式的一次呼叫執行結束後,變數被撤銷,其所佔用的記憶體也被收回。
  • 靜態區域性變數:具有區域性作用域,它只被初始化一次,自從第一次被初始化直到程式執行結束都一直存在。
**************************C語言中的static的用法********************************
*******************************************************************************
static變數 ( 修飾全域性變數 與 區域性變數) 的例子:
#include<stdio.h>
static int j; //修飾靜態的全域性變數
int funOne(void)
{
        static int i = 0;//修飾靜態的區域性變數
        i++;
        return i;
}

int funTwo(void)
{
        j = 0;
        j=j+2;
        return j;
}

int main()
{
        int k = 0,m = 0,n = 0;
        for(k = 0;k < 5;k++)
        {
                m = funOne();
                n = funTwo();
                printf("m=%d,n=%d\n",m,n);
        }
        return 0;
}
****************結果顯示如下****************
m=1,n=2
m=2,n=2
m=3,n=2
m=4,n=2
m=5,n=2
************對結果的解釋說明************
對於funOne( ),執行一次之後,變數i保持了原來的資料,並沒有銷燬,而是在下一次呼叫的時候繼>續使用,所以才會有1、2、3…5這樣的結果。而對於funTwo( ),執行一次之後,變數j的值被銷燬了,所>以第二次呼叫結束j仍然保持原值“1”,所以迴圈五次,每次都是1
1、static修飾全域性變數——靜態全域性變數

    使用方法:在全域性變數前面加static關鍵字,例如:static int i = 0;

    初始化:未經初始化的全域性變數會被自動初始化為0(自動物件的值是任意的,除非他被顯示初始化);

    儲存的位置:靜態儲存區 (static) ,全域性變數和靜態變數是儲存在一起的,初始化的全域性變數和靜態變數在一塊區域,未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域,程式結束後由系統自動釋放。

    變數的作用域:具有全域性作用域,只初始化一次,它與全域性變數的區別在於如果程式包含多個檔案的話,它作用於定義它的檔案裡,不能作用到其它檔案裡,即被 static 關鍵字修飾過的變數具有檔案作用域。(使得作用域僅限於被定義的檔案中 即,從變數定義到本檔案結尾處,其他檔案不論通過什麼方式都不能訪問)。

    總結:靜態區域性變數值初始化一次;若不賦初值,在初始化的時候會自動賦值為0;只作用於定義他的檔案中,不能作用於其他的檔案中;把全域性變數改變為靜態變數是改變了他作用域。

2、static修飾區域性變數——靜態區域性變數

使用方法:在區域性變數前面加static關鍵字,例如:static int j; 

    初始化:未經初始化的區域性變數會被自動初始化為0(自動物件的值是任意的,除非他被顯示初始化);

    儲存的位置:靜態儲存區 (static) ,全域性變數和靜態變數是儲存在一起的,初始化的全域性變數和靜態變數在一塊區域,未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域,程式結束後由系統自動釋放。

    引入靜態區域性變數的原因:

            通常再函式體內定義了一個變數,每當程式執行到改函式時候就會給區域性變數分配棧記憶體,但隨著程式退出函式體,系統就會收回棧記憶體,區域性變數也響應的失效。但是有的時候我們需要在兩次呼叫之間對變數的值進項儲存。通常的想法是定義一個全域性變數來實現。但是這樣一來,變數就已經不再屬於函式本身了,不再僅受函式的控制,給程式的維護帶來不便利。靜態區域性變數正好解決了這個問題,靜態區域性變數儲存在全域性資料區(靜態儲存區),而不是儲存在棧中,每次的值保持到下一次呼叫,直到下一次賦新值。

     變數的作用域:具有區域性作用域,它只被初始化一次,自從第一次被初始化直到程式執行結束都一直存在。(當定義他的函式或者語句塊結束的時候,作用域結束,但是當局部靜態變數離開作用域後,並沒有被銷燬,而是仍然駐留在記憶體當中,只不過我們不能再對他進行訪問,直到改函式再次被呼叫嗎,並且值不變)

  總結:靜態區域性變數值初始化一次;若不賦初值,在初始化的時候會自動賦值為0;只對定義自己的函式體始終可見;把區域性變數改變為靜態變數是改變了他的儲存方式即改變了他的生存週期。

    靜態區域性變數與動態區域性變數的區別:

(1)靜態區域性變數資料屬於靜態儲存類別,在靜態儲存區內分配記憶體單元,在整個程式執行期間都不釋放。而自動變數(即動態區域性變數)屬於動態儲存類別,佔動態儲存區空間而不佔

用靜態儲存區空間,函式呼叫結束後立即釋放空間。

(2)靜態區域性變數時在編譯時被賦值的,即自始至終只賦值一次,在程式執行時它已經有初值。以後每次呼叫函式時不再重新賦初值而只是保留上次函式呼叫結束時的值。而自動變數賦初值,不是在編譯時進行的,而是在執行時進行,所以每呼叫一次函式就賦一次初值。

(3)如在定義區域性變數時不賦初值,則對靜態區域性變數來說,編譯時自動賦一個初值0(對數值型變數)或空字元(對字元變數)。而對自動變數來說,如果不賦初值,則它的值是一個不確定的值。這是由每次動態分配的記憶體單元不同所決定的。

static變數 ( 修飾全域性變數 與 區域性變數) 的例子:  

/*在text.c檔案中*/
int func_int()
{
        return 2;
}

static int func_static()
{
        return 3;
}
/*在main.c檔案中*/
#include<stdio.h>
void main()
{
        int temp2 = func_int(); 
        int temp3 = func_static();              
        printf("temp2 = %d\n",temp2);
        printf("temp3 = %d\n",temp3);
}  
//編譯連結[[email protected] C_function]# gcc main.c test.c

        驗證的時候可以先把 後面兩行註釋掉int temp3 = func_static(); printf("temp3 = %d\n",temp3); 

***************結果顯示如下*************
[[email protected] C_function]# gcc main.c test.c 
/tmp/ccg1gHfy.o: In function `main':
main.c:(.text+0x1b): undefined reference to `func_static'
collect2: error: ld returned 1 exit status

3、static修飾函式——靜態函式(內部函式)

在函式前加static,則此函式成為靜態函式(內部函式),我們用static修飾函式的主要目的是:用來表示不能被其它檔案訪問的一個函式(和用static修飾全域性變數的目的一樣,都是不允許其它檔案訪問)。這樣一來便有一個好處:程式設計師不用擔心自己編寫的函式與其他檔案的函式同名。(對於可在當前原始檔以外使用的函式,應該在一個頭檔案中說明,要使用這些函式的原始檔要包含這個標頭檔案


參考的網址:

1》變數在記憶體中的存放區別:https://www.cnblogs.com/bakari/archive/2012/08/05/2623637.html

2》C\C++中STATIC的用法:https://www.cnblogs.com/jhmu0613/p/7131997.html

3》四個變數間的區別:https://www.cnblogs.com/zhangwuji/p/5297631.html

4》部分記憶體的分佈情況:https://blog.csdn.net/jsjwql/article/details/1788286

相關推薦

C語言 static作用——修飾 變數全域性變數/區域性變數函式

*******************************概念*********************************************************************************************************

C語言那年踩過的坑--區域性變數,靜態變數全域性變數在記憶體中存放的位置

  先看幾個概念: 1、bss是英文block started by symbol的簡稱,通常是指用來存放程式中未初始化的全域性變數的一塊記憶體區域,在程式載入時由核心清0。bss段屬於靜態記憶體分配。它的初始值也是由使用者自己定義的連線定位檔案所確定,使用者應該將它定義在可讀寫的ram區內,源程式中使用m

C語言二叉樹建立一定看的懂

  先貼一個百度出來的二叉樹的圖 二叉樹 就是首先得有一個根節點.這個節點的入度為0也就是它只有子節點沒有父節點 如1號節點     每個節點又有一個左兒子和一個右兒子 當然也可以沒有 接下來就是建立.建立一棵樹得現有這棵樹的結點和樹根

c語言演算法—01揹包問題一維表達形

經過上次我們用基礎的演算法解決了揹包問題之後,現在我們來看另外一種演算法:通過一維陣列表達; 其實,在上次我們使用二維陣列時可以發現,我們在從上往下建立(橫向建立)的時候,資料是一行一行成型的,而新的資料是在原先一排舊的基礎上更新形成的,所以,我們來想,我們其

C語言再學習 -- 段錯誤核心已轉儲

一、什麼是段錯誤?一旦一個程式發生了越界訪問,cpu 就會產生相應的保護,於是 segmentation fault 就出現了,通過上面的解釋,段錯誤應該就是訪問了不可訪問的記憶體,這個記憶體區要麼是不存在的,要麼是受到系統保護的,還有可能是缺少檔案或者檔案損壞。二、段錯誤產

C語言陣列去重排序從大到小

好久沒寫程式了,改了好久也只能寫成這樣,勉強能用 #include<stdio.h> void bubble_sort(int *arr,int len) {       int i, j,temp;        for(i=0;i<len;i+

java開發C語言編譯器:jvm的return指令以及區域性變數的操作

請結合視訊閱讀本文以便獲得更清晰的理解。 更詳細的講解和程式碼除錯演示過程,請參看視訊 用java開發C語言編譯器 如果你對機器學習感興趣,請參看一下連結: 機器學習:神經網路導論 jvm執行位元組碼時,程式碼的執行必須圍繞兩種資料結構,一種

使用C語言列印不同星號圖案矩形 平行四邊形 三角形

獻給大一或大二的學弟學妹們和在自學 C語言的同志們。 列印自定義行數的矩形 列印效果: 參考程式碼: #include<stdio.h> int main

c語言實現二叉樹二叉連結串列非遞迴後序遍歷

演算法思想 因為後序遍歷是先訪問左子樹,再訪問右子樹,最後訪問根節點。當用棧實現遍歷時,必須分清返回根節點時,是從左子樹返回的還是從右子樹返回的。所以使用輔助指標r指向最近已訪問的結點。當然也可以在節點中增加一個標誌域,記錄是否已被訪問。 #include<iost

C語言】動態記憶體分配malloc,realloc,calloc,free的基本理解和區別

#include<Windows.h> #include<stdio.h> #include<malloc.h> int main() { int* p = NULL; printf("%x\n", p); p = (int*)malloc(sizeof(int)*

c語言入門:指標運用 用逗號切割字串

#include <stdio.h> #include <string.h> #include <stdlib.h> /** * 列印陣列 * @brief printfArray * @param array * @

c語言將資料寫入檔案用連結串列實現

/*c語言將資料寫入檔案,用連結串列實現*/ #include #include #include /*定義結構體*/ typedef struct Node { char id[10];

C語言 整數的整數次方不考慮大數問題

#include<stdio.h> int doublepow(int n, int m) { int i = 1; int sum = n; for(i = 1; i< m; i++) { s

C語言實現迴文判斷利用指標的方法

//判斷迴文(指標實現) #include <stdio.h>   #include <stdlib.h>   #include <string.h>       void IsSymmetrical(char *str)   {  

C語言自學之路二linux相關知識二

文件傳輸協議 創建 .gz all 使用 登錄系統 開啟 界面 當前位置 linux快捷鍵 快捷鍵 效果 Ctrl+Z 程序轉入後臺 Ctrl+Alt+T 快速進入終端 F2 修改文件名 關鍵命令行 命令行 效 果 mv 文件名1

js的變數作用域,區域性變數全域性變數全域性區域性變數重名

一、變數的作用域:  變數起作用的範圍,變數在啥地方能用。那麼啥地方就是它的作用域。二、變數作用域分為:區域性變數和全域性變數。1、區域性變數://就是定義在函式內部的變數(內部變數),區域性變數起作用的範圍是函式內部。//區域性變數就是私有的變數2、全域性變數://就是定義

JAVA關鍵字Static作用 特點 利弊及建立時機 成員變數和靜態變數 Static修飾成員 修飾方法 修飾靜態快

(1)Static關鍵字修飾符 可以修飾成員(成員屬性 成員方法)(2)Static修飾成員的特點a 生命週期長 跟類相同b 用Static修飾的變數 所有物件共享c Static修飾變數 可以通過物件(.)點的形式呼叫 還可以通過類名(.)點方法呼叫(3)Static建立時

C語言 static靜態變量的作用

middle sel ide mic 進行 otto pla .net round C語言 static靜態變量的作用static c語言的變量種類 靜態變量通過關鍵字 static 進行聲明,該變量存儲在數據段上,也就是內存上,可以改變變量的作用域和生命周期。 對於

C++語言學習——C++C語言基礎語法的擴展

情況下 ces qtcreator 缺少 命令 ast 過多 匯編 lse C++語言學習(二)——C++對C語言基礎語法的擴展 C++是基於C語言擴展發展而來的面向對象的程序設計語言,本文將主要討論C++語言基於C語言擴展的方面。 一、實用性增強 C語言中變量的定義必須在

C++C語言的拓展4—— 函數重載

over 及其 尋求 所有 print har nbsp erro erl   函數重載(Function Overload):用同一個函數名定義不同的函數,當函數名和不同的參數搭配時函數的含義不同。 1、重載規則 (1)函數名相同; (2)參數個數不同,參數的類型不同,參