在c語言中,所有變數、巨集、函式(函式的宣告形式即為函式原型)、自定義資料型別以及別名等資料必須先宣告後使用。通常在標頭檔案中包含這些宣告,如extern int global_data,這個宣告只是告訴編譯器全域性變數的型別和名字,至於對它的定義(分配記憶體的宣告即為定義)則在別處進行。
1、作用域
在c語言中,常見的有**塊(一對花括號之間的**)作用域和檔案作用域。
所有函式之外定義的變數叫作全域性變數(也叫外部變數,預設具有靜態儲存特性)。某個**塊之內定義的變數(包括函式定義中的引數)就是區域性變數(預設具有動態儲存特性,使用static修飾會使用區域性變數具有靜態特性)。區域性變數只具有空鏈結特性,即只能在定義它的**塊中被訪問。
知識點:
(1)、具有靜態儲存期的變數在程式執行過程中一直存在。而具有動態儲存期的變數只有在執行到這些變數所屬的**塊時才為其分配記憶體,並且在退出此**塊時,就釋放掉所分配的記憶體。
舉例,如清單1:
#include char *func(void)
int main(void)
用gcc編譯時,會警告說函式不能返回區域性變數的位址。程式執行時,不能正確輸出陣列a中的字元,只是一些亂碼,那是因為在第14行的函式呼叫之後,陣列a就已經被釋放掉了。
(2)、在程式設計師未明確賦初始值的情況下,編譯器自動把靜態變數(即具有靜態儲存期的變數,包括全域性變數和用static修飾的區域性變數)初始化為0或null(這個值是針對指標變數而言的),而動態變數(即具有動態儲存期的變數)的初始值是不確定的。
2、傳值呼叫
由於函式中的資料只為本函式所有,所以在c語言中,函式之間交往資料的通路只有兩種:全域性變數和傳值呼叫。
普通變數的傳值呼叫,如清單2:
#include void func(int a, int b)
int main(void)
例子輸出結果:
in func, address a = 0xbf8cc770, b = 0xbf8cc774
in func, value a = 3, b = 4
in main, address a = 0xbf8cc78c, b = 0xbf8cc788
in main, value a = 3, b = 4
在main函式中,通過函式傳值呼叫(例子中的第14行)把變數a和b的值傳給func函式中的a和b(整個傳值過程就相當於賦值)。注意,這兩個函式中的變數a和b雖然同名,但互不影響,屬於不同的變數,從結果中它們的位址就可知。
與指標變數有關的傳值呼叫,如清單3:
#include void func(int *p1, int *p2)
int main(void)
例子輸出結果:
before calling, a = 3, b = 4
after calling, a = 8, b = 9
在main函式中,把變數a和b的位址(也是乙個數值)傳給func函式中的指標變數p1和p2,然後通過間接運算子來改變a和b的值。
相對複雜的例子,如清單4:
#include #include #include void func(char *p)
int main(void)
在例子中,通過函式呼叫,把指標變數str的值null傳遞給func函式的指標變數p,而後p的值又被malloc函式返回的位址所覆蓋,其實例子中的函式呼叫對str值的改變沒有任何影響,一直都是null,而往null中拷貝資料會產生段錯誤。
注意,用函式malloc分配的記憶體必須通過free函式來釋放,否則在程式執行過程中,所分配的記憶體一直被占用。
php 函式變數作用域(傳值與傳應用)
php中變數預設是傳值賦值,既當將乙個表示式的值賦予乙個標量時,整個原始表示式的值被賦值到目標變數。這意味著,當乙個變數的值賦予另外乙個變數時,改變其中乙個變數的值,將不會影像另外乙個變數。php也提供了另外一種方式給變數賦值 引用賦值。這意味著新的變數簡單引用 指向 原變數位址 了原始變數。改動新...
傳值呼叫與傳址呼叫
眾所周知,函式的呼叫分為傳值呼叫和傳址呼叫,那他們的區別是什麼呢?傳值呼叫 函式的形參和實參分別占有不同的記憶體塊,對形參的修改不會影響實參。傳址呼叫 傳址呼叫是把函式外部建立變數的記憶體位址傳遞給函式引數的一種呼叫函式的方法。這種傳參方式可以讓函式和函式外邊的變數建立起真正的聯絡,也就是函式的內部...
函式呼叫和傳值呼叫
在使用函式時,所有的實參都是通過 傳值 方式傳遞的。這意味著每個實參都被求值,求值結果代替對應的形式引數,並且在函式中作為區域性變數使用。如果乙個變數傳遞給乙個函式,這個變數在呼叫環境中所儲存的值並不會被函式所修改。include int compute sum int n int main voi...