c語言變數的作用域,連結屬性,儲存型別&&static關鍵字

gogogo_sky發表於2017-05-16

http://blog.csdn.net/mingzhentanwo/article/details/43524383

一、作用域:

變數在程式的某個部分宣告時,只能在程式的一定區域內才能訪問,這個區域就成為作用域
作用域分為四種:
①檔案作用域②函式作用域③程式碼塊作用域④原型作用域。
編譯器通過變數宣告的位置來確定作用域

(1)檔案作用域

當變數在所有程式碼塊之外宣告時就在檔案作用域中,檔案作用域的範圍是從變數宣告處一直到檔案的結束。但如果變數的宣告在“.h”檔案中,並且該“.h”檔案被其他檔案用#include 所包含,那該變數的作用域也會相應的擴大到包含檔案的結束。

(2)函式作用域

函式作用域只適用於語句標籤,語句標籤用於goto語句。一個函式作用域內的語句標籤必須唯一。

(3)程式碼塊作用域

宣告位於一對大括號之間,有效範圍從宣告開始至程式碼塊結束。

(4)原型作用域

原型作用域 適用於在函式宣告中的引數名,只適用於函式宣告的括號內;

二、連結屬性

連結屬性決定如何處理在同一個專案位於不同檔案內的識別符號。連結屬性共有三種——①external(外部)、②internal(內部)、③none(無)。

  • 連結屬性為none的識別符號不論在那個檔案內都是獨立的個體
  • 連結屬性為internal的識別符號在同一個原檔案內的所有宣告均指向同一個實體,不能在其他檔案中使用extern關鍵字被使用;
  • 連結屬性為external的識別符號不論宣告多少次,位於幾個原檔案內均表示同一實體,可以在其他檔案中使用extern關鍵字宣告使用;

    在檔案作用域內宣告的變數或是函式,在預設的條件下連結屬性為external(相當於前面加了extern),其餘的為none

(1)extern關鍵字

如果使用externa關鍵字宣告某一個變數,說明該變數在別的地方定義的,可能位於別的檔案也可能位於當前檔案。該關鍵字制定識別符號的連結屬性為external,在一個專案中 ,在一個檔案內部可以通過extern關鍵字訪問由別的檔案定義的變數,但此時不能在使用extern修飾變數的同時給該變數賦初值

例1:在test2.c檔案中使用test1.c檔案中的變數a,且變數a屬性為external.
會出錯: 找到一個或多個多重定義的符號

//test1.c
#include<stdio.h>
int a=0;
void fun1()
{
    printf("%d\n",a);
}
//test2.c
#include<stdio.h>
int a=1;
void fun2()
{
    printf("%d\n",a);
}
//main.c
#include<stdio.h>
void fun1();
void fun2();
int main()
{
    fun1();
    fun2();
    return 0;
}

出錯: 找到一個或多個多重定義的符號

例2:在test2.c檔案中使用關鍵字extern宣告,使用test1.c檔案中的變數a,此時,test2.c中的a值就是test1.c中的a值;且變數a屬性為external;然後在main.c中使用extern宣告a;此時,在三個原始檔中使用的a為一個記憶體中的a,
這時,三個只要改了一個原始檔的a值,三個原始檔當中的a值都會改變;
程式正確

//test1.c
#include<stdio.h>
int a=0;
void fun1()
{
    printf("%d\n",a);
}
//test2.c
#include<stdio.h>
extern int a;
a=1void fun2()
{
    printf("%d\n",a);
}
//main.c
#include<stdio.h>
void fun1();
void fun2();
int main()
{
    extern int a;
    fun1();
    fun2();
    a=10;
    fun1();
    fun2();
    return 0;
}

//結果:0 ,0 , 10 , 10

(2)static關鍵字

如果一個識別符號的連結屬性為external,那麼static可以將其連結屬性改為intern,此時static修飾的變數或者函式名,都只能在本檔案中使用,不能使用extren關鍵字在別的檔案中宣告使用;此時別的檔案可以命名和靜態變數或者函式相同的變數名或者函式名;此時,在別的檔案中如果使用extren宣告和靜態變數的變數名或者函式名相同的名字,並對其變數做改變;此時靜態變數或者函式不改變,含有相同名變數的檔案裡面的變數會改變;
例1、test1.c中定義一個全域性靜態變數,此時該變數的連結屬性從external變為internal;在test2.c中定義了一個和變數名相同的變數;可以成功定義;
此時test2.c中的a的連結屬性為external;在main.c中使用extren關鍵字宣告a變數;實際是宣告的test2.c中的a變數;在main.c中對a做修改,只是改變了
test.2中的a;

//test1.c
#include<stdio.h>
static int a=0;
void fun1()
{
    printf("%d\n",a);
}
//test2.c
#include<stdio.h>
int a=10;
void fun2()
{
    printf("%d\n",a);
}
#include<stdio.h>
void fun1();
void fun2();
int main()
{
    extern int a;
    fun1();
    fun2();
    a=100;
    fun1();
    fun2();
    return 0;
}

//結果:0 ,10, 0, 100

三、儲存型別

儲存型別(儲存位置)分為普通記憶體執行時堆疊硬體暫存器
變數的預設型別取決於它的儲存型別:
•在程式碼塊之外宣告的變數總是儲存在靜態記憶體中,這種變數稱為靜態變數。無法改變這種變數的儲存型別。靜態變數在程式執行之前建立,在整個程式執行時一直存在直至結束才被銷燬。
•在程式碼塊內宣告的變數預設儲存型別為自動的,儲存在堆疊內。每次函式被呼叫時,這些變數的儲存的位置可能不同。如果用static來修飾一個函式內的變數,就可以將他轉變為靜態的,靜態儲存型別的變數在整個程式執行的過程中一直存在,而不僅僅是在它所在的程式碼塊執行的時候存在,修改變數的儲存型別,不會改變的該變數的作用域,它只能在該變數內部按名字訪問※只是每次函式被呼叫時,該變數的值仍為上次函式結束時的值。
•用register修飾的變數成為暫存器變數,通常,這種變數的訪問速率比在記憶體中的變數訪問速度快。

四、static關鍵字

(1)當static用於程式碼塊之外時,static用於修改識別符號的連結屬性從external修改為static
當static用與程式碼塊內部時,static用於修改識別符號的儲存型別,將其從自動變數修改為靜態變數
這裡寫圖片描述

相關文章