1. 程式人生 > >4_C語言中的作用域、連結屬性與儲存屬性

4_C語言中的作用域、連結屬性與儲存屬性

C 作用域

作用域是程式中定義的變數所存在的區域,超過該區域變數就不能被訪問。編譯器可以確認4種不同型別的作用域:檔案作用域,函式作用域,程式碼塊作用域,原型作用域。

程式碼塊作用域

位於一對花括號之間的語句稱為語句塊,任何在程式碼塊的開始位置宣告的識別符號都具有程式碼塊作用域,表示它們可以被這個程式碼塊中的所有語句訪問。

當代碼塊巢狀時,聲明於內層程式碼塊的識別符號的作用域到達該程式碼塊的尾部就結束,如果內層程式碼塊有一個識別符號與外層的程式碼塊的識別符號同名,內層的識別符號將隱藏外層的識別符號。

檔案作用域

任何在所有程式碼塊之外宣告的識別符號都具有檔案作用域(file scope)。並且,通過#include指令包含到其他檔案中的宣告就好像它們是直接寫在那些檔案中一樣。它們的作用域並不侷限於標頭檔案的檔案尾。

原型作用域

原型作用域(prototype scope)只適用於在函式原型中宣告的引數名,將它獨立出來只是為了這個名字不能與其他作用域的符號混淆,它其實沒有什麼用,甚至都可以不寫。事實上,唯一可能出現的衝突就是在同一個原型中不止一次使用同一個名字。

函式作用域

它只適用於語句標籤,用於goto語句。

連結屬性

當組成一個程式的各個原始檔分別被編譯之後,所有的目標檔案以及那些從一個或多個函式庫中引用的函式連結在一起,形成可執行檔案。問題是,如果相同的識別符號出現在幾個不同的原始檔中時該怎麼辦?識別符號的連結屬性決定如何處理在不同檔案中出現的識別符號。識別符號的作用域與它的連結屬性有關,但這兩者並不相同。

連結屬性一共有3種:

1.none(無)

總是被當做單獨的個體,也就是說該識別符號的多個宣告被當作獨立不同的實體。

2.internal(內部)

在同一個原始檔中的所有宣告中都指向同一個實體,但位於不同原始檔的多個宣告則分屬不同的實體。

3.external(外部):

不論宣告多少次、位於幾個原始檔都表示同一個實體。

extern和static兩個關鍵字可以用於設定識別符號的連結屬性。當沒有這兩個關鍵字時,預設的連結屬性與識別符號的作用域相關。

typedef char *a;

int b;

int c(int d)

{

    int e;

    int f(int
g); ... }

上面的程式碼塊中,b、c、f有external連結屬性,f在本程式碼中被呼叫,定義在其他原始檔或者庫中,所以也是external屬性。其他的識別符號都是none屬性。 

static關鍵字可以把一個預設為external屬性的識別符號改為internal,如上例中,可以把b、c的連結屬性改為internal,使其在其他原始檔中不可見。 

static int b;

static int c(int d);

extern 關鍵中可以把none屬性改為external屬性。

 

// linkage_test1.c

#include<stdio.h>

 

extern int a; // 可選,因為預設就是external

              // 但是應該寫上,增加程式可讀性

 

int main() {

    printf("a = %d\n", a);

    extern int b; // 必需,預設為none

    printf("b = %d\n", b);

}

最後,當extern關鍵字用於原始檔中一個識別符號的一次宣告時,它指定該識別符號具有external連結屬性,但是,如果它用於該識別符號的第2次或者以後的宣告時,它並不會更改由第一次宣告所指定的連結屬性。如下例所示: 

static int i;

int func()

{

    extern int i; //i的連結屬性仍然為static

}

C 儲存類別

變數的儲存型別是指儲存變數值的記憶體型別。變數的儲存型別決定變數何時建立、何時銷燬以及它的值將保持多久。有三個地方可以用於儲存變數:普通記憶體、執行時堆疊、硬體暫存器。在這三個地方儲存的變數具有不同的特性。

儲存類定義 C 程式中變數/函式的範圍(可見性)和生命週期。這些說明符放置在它們所修飾的型別之前。下面列出 C 程式中可用的儲存類:

普通記憶體變數

變數的預設儲存型別取決於它宣告的位置(作用域),凡是在任何程式碼塊之外宣告的變數總是儲存與靜態記憶體中,也就是不屬於堆疊的記憶體,這類變數稱為靜態變數。

可以通過static關鍵字將一個程式碼塊內部變數由堆疊型別變為靜態型別。static修飾區域性變數時,變數在程式的生命週期內都存在,不需要在每次它進入和離開作用域時進行建立和銷燬。

static 修飾全域性變數,和全域性函式時,會使變數的作用域限制在宣告它的檔案內。

堆疊變數

在程式碼塊內部宣告的變數的預設儲存型別是自動的,可以使用關鍵字auto指定,但它極少使用,因為完全沒必要。這些自動變數存在堆疊中。

硬體暫存器變數

可以通過關鍵字register來指定,提示程式執行時用硬體暫存器來儲存該變數,但是定義 'register' 並不意味著變數將被儲存在暫存器中,它意味著變數可能儲存在暫存器中,這取決於硬體和實現的限制。

register 儲存類用於定義儲存在暫存器中而不是 RAM 中的區域性變數。這意味著變數的最大尺寸等於暫存器的大小(通常是一個詞),且不能對它應用一元的 '&' 運算子(因為它沒有記憶體位置)。

暫存器只用於需要快速訪問的變數。

作用域、連線屬性和儲存型別總結

變數型別

宣告的位置

是否存在於堆疊中

作用域

如果生命宣告成static

全域性

多有程式碼塊之外

從宣告處到檔案結尾

不允許從其它檔案訪問

區域性

程式碼塊起始處

整個程式碼塊

變數將不儲存堆疊中,在程式執行時將會一直存在

形式引數

函式頭部

整個函式

不允許

相關推薦

4_C語言作用連結屬性儲存屬性

C 作用域 作用域是程式中定義的變數所存在的區域,超過該區域變數就不能被訪問。編譯器可以確認4種不同型別的作用域:檔案作用域,函式作用域,程式碼塊作用域,原型作用域。 程式碼塊作用域 位於一對花括號之間的語句稱為語句塊,任何在程式碼塊的開始位置宣告的識別符號都具有程

作用連結屬性儲存型別

最近在讀《程式設計師的自我修養——連結、裝載與庫》,感覺自己當初學習C的時候,對extern、static等關鍵字瞭解不是特別清晰,因此重溫了一遍《C和指標》中關於作用域、連結屬性和儲存型別的相關部分,加上了自己的理解,用部落格記錄一下。 --- ## 作用域 **當變數在程式的某個部分被宣告時,它只有

Go語言基礎(八)—— Go語言變數作用Go語言陣列Go語言指標

Go語言變數作用域 作用域為已宣告識別符號所表示的常量、型別、變數、函式或包在原始碼中的作用範圍。  Go 語言中變數可以在三個地方宣告: • 函式內定義的變數稱為區域性變數  • 函式外定義的變數稱為全域性變數  • 函式定義中的變數稱為形式引數&nb

c語言 作用存儲期鏈接屬性匯總

初始 執行 不存在 分配 標識符 num 賦值 inline bss 1、作用域   塊作用域:用{}闊起來的,從聲明開始到“}” 結束 函數作用域:goto(標識符) 的作用域為整個函數。 函數原型作用域:函數聲明開始,函數聲明結束而結束

C語言變量全局變量變量的作用

www. 但是 表達 之間 範圍 htm target 因此 變量名 什麽是變量: 變量常量都是表征數據的一種形式;常量用來表示數據的值; 變量不僅可以用來表示數據的值;還可以用來存放數據;因為變量對應著一定的內存單元; 變量和常量必須先定義後使用。 變量名和常量名都是一種

Head First Servlets and JSP】筆記9:屬性作用線程安全

string details attr target 部分 ring 瀏覽器 什麽是 作用 什麽是屬性? 屬性和參數 屬性的3個作用域 屬性API 屬性不好的一面 1、到底什麽是屬性(Attribute)? 屬性就是一個對象,可以被設置(bound,也可以

Python之路Python作用匿名函式函數語言程式設計map函式filter函式reduce函式 Python之路Python作用匿名函式函數語言程式設計map函式filter函式reduce函式

Python之路Python作用域、匿名函式、函數語言程式設計、map函式、filter函式、reduce函式 一、作用域 return 可以返回任意值例子 def test1(): print("test1") def test(): print("te

SpringBean定義作用管理問題

一、Bean的定義 <beans…/>元素是Spring配置檔案的根元素,<beans…/>元素可以包含多個<bean…/>子元素,每個<bean…/>元素可以定義一個Bean例項,每一個Bean對應Spring

一些概念:類和結構名稱空間複製建構函式作用連結性 自動變數和堆疊

  1、類和結構       類描述看上去很像是包含成員函式以及public和private可見性標籤的結構宣告。實際上,C++對結構進行了擴充套件,使之具有與類相同的特性。他們之間唯一的區別是,結構的預設訪問型別是public,而類為pri

C語言關鍵字autostaticregisterexternvolatilerestrict的作用

(1):auto關鍵字在C語言中只有一個作用,那就是修飾區域性變數。 (2):auto修飾區域性變數,表示這個區域性變數時自動區域性變數,自動區域性變數分配在棧上。(既然是分配在棧上,說明他如果不初始化的話那麼值就是隨機的....)  (3):平時定義區域性變數時就是定義的auto的,只是省略了auto關鍵字

python day10 python作用 lambda表示式(又稱匿名函式) 函數語言程式設計 遞迴函式 recursion

目錄: python作用域 、lambda表示式(又稱匿名函式) 、 函數語言程式設計 、 遞迴函式 recursion python作用域: 定義: 作用域也叫名稱空間,是訪問變數時查詢變數名的範圍空間 python的四個作用域LE

C語言的常量變數及其屬性,型別儲存空間

部落格源地址  http://www.codertown.cn/blog/?p=134 常量和變數其實就是C語言裡的值,其他程式語言同樣存在,這個跟數學裡的是一樣的。 1、常量 固定的值,不可改變的值是常量,幾種型別: 在表示式中直接用數值表示;巨集定義當然也是

C語言關鍵字staticextern和auto的作用總結

1、首先說一下auto自動儲存型別,一般我們很少在程式中顯示申明變數為auto型別。因為程式碼塊中的變數預設情況下就是這種型別,這種型別的變數存放於堆疊中,也就是說只有程式執行這些程式碼塊(一對{}之間的語句)時這種自動變數才會被建立,程式碼塊執行結束後自動變數便被釋放。

關於C語言變數生存週期作用記憶體分佈預設值的基本總結

在C語言中,參與計算的資料都是通過不同型別的常量或者變數來表示的,而使用變數時不得不注意變數的生存週期、作用域,記憶體區域和預設值。在這裡簡單介紹一下記憶體區域: 程式碼段(code segment)

Jsarguments的使用函式自呼叫變數作用函式作為引數傳入函式作為返回值

1,arguments是一個比較特別的物件,每個函式中都有一個arguments,它接收函式傳入的引數,以陣列的形式存放在 arguments,可遍歷 //1,需求:求任意數的最大值 function getMax(){ var Max = arguments

SpringBean的作用生命周期

作用域 spring容器 分享 引用 多少 返回 portlet type 精確 Bean的作用域(scope)   Spring 3定義了五種作用域,分別為singleton(單例)、prototype(原型)、request、session、global sessio

自動類型轉換強制類型轉換作用整型表數範圍

基本類 logs 自動類型轉換 四種 main print 輸出字符串 縮小 stat 一、變量的作用域 測試代碼: public class Test1 { private static int value = 1; // 全局變量 pri

C語言字符字符串字符數組

文件 getc order 知識點 技術 ima 數組 c語言 align char a = ‘h‘; memory h char a[] = "Hello"; memory H e l l o ‘\0‘ stri

python基礎之名稱空間和作用函數嵌套

空間 dir pri 引用 value log 關系 fun ret 一、名稱空間 1、定義:存放名字與值的綁定關系 2、名稱空間分為:內置名稱空間、全局名稱空間、局部名稱空間 內置名稱空間:python解釋器自帶的名字,python解釋器啟動就會生成 全局名稱空間:文件級

C/C++作用詳解(轉)

防止 局部作用域 gist 文件中 方式 為什麽不使用 形式參數 lan archive 作用域規則告訴我們一個變量的有效範圍,它在哪兒創建,在哪兒銷毀(也就是說超出了作用域)。變量的有效作用域從它的定義點開始,到和定義變量之前最鄰近的開括號配對的第一個閉括號。也就是說,作