c語言中在發生有參函式呼叫時,實參變數與形參變數之間的資料都是單向的「值傳遞」方式。包括指標變數和陣列名作引數的情況。
c語言要求函式的實參要有確定的值,在函式呼叫時給形參分配相應的記憶體單元,同時將實參的「值」賦(複製)給形參,實現資料從實參到形參的傳遞(『值傳遞』方式)。因為是複製,所以在操作副本(形參)過程中不會影響到原本(實參)內容。
首先,作為函式實參的量包括常量、變數和表示式。其中變數又包括簡單變數、陣列元素、陣列名、指標變數等。不同型別變數作引數實現的資料傳遞方式相同,效果不同。
所謂方式相同即都是引數間資料單向的「值傳遞」,效果不同是指被調函式能否改變主調函式中變數的值。
情況一:簡單變數或陣列元素作為函式引數
陣列元素本身屬於簡單變數,在向形參傳遞資料時,根據前述規則只需將變數中的「值」複製乙份放到形參變數中去操作,此時在被呼叫函式中操作的物件(形參)與實參並不在同一記憶體單元,並且在呼叫結束後形參所佔記憶體單元被釋放,因此呼叫函式不會影響到實參變數的值。同時被調函式也不會影響到主調函式中其他變數的值。
例:1#include
void main()
f(int a)
例2#include
void main()
,f(int a);
printf("%d%d",a[0],f(a[0]));
}f(int a)
情況二:指標變數或陣列名作為函式引數
1.指標變數作函式引數
指標變數作實參在呼叫時仍然符合前述「值傳遞」規則,將其「值」賦給形參,相當於複製。此時資料在實參與形參間傳遞仍是單向的,呼叫函式不會影響實參的「值」(即指標變數中所存位址)。而與簡單變數不同的是指標變數複製給形參的「值」本身是乙個位址,這個位址為形參訪問其所指變數創造了可靠條件。我的理解是,實參是乙個抽屜的鑰匙,在傳參時,實參複製了一把鑰匙傳給形參。而被調函式拿到鑰匙副本後,進行的操作可以分為兩類:1、對鑰匙本身做了一些操作(對指標本身進行操作);2、通過鑰匙對抽屜裡的內容進行了一些操作( 對指標所指的變數進行操作);兩種操作都不可能影響實參的值(即鑰匙原本),卻有可能改變實參所指向變數的值(即抽屜裡的內容)。
例1#include
void main()
void swap(int*p1,int*p2)
例2#include
void main()
void swap(int*p1,int*p2)
2.陣列名作函式引數
陣列名本身是乙個特殊的指標變數,其值是陣列的首位址,因此作實參時其傳給形參的是記憶體中某指定單元的位址,呼叫過程中形引數組與實參陣列占用同一段記憶體單元,因此對形引數組的操作也就是對實參陣列的操作,對實參陣列與形引數組來說資料傳遞表現為「雙向」的,而對實參變數與形參變數而言資料的傳遞仍然是單向的。
例#include
void main()
;void f(int a);
f(a);
for(i=0;i<3;i++)
printf("%d",a[i]);
}void f(int a)
情況三:引用作為函式引數:
首先申明引用和指標最大的不同是:引用本身不是變數,不存在自己的變數空間,引用只是乙個作為變數別名的標誌。
引用必須依託於乙個已實際存在的變數,正如乙個人的如果連正名都沒有,就無所謂小名了。正因為引用只是為了方便為同乙個變數所取的小名,所以在任何地方通過引用對變數的操作和通過變數名進行操作的結果是一樣的。
綜上,當引用作為函式引數時,對形參的操作既是對原變數的操作,可以改變實參的值。效果上雖然和通過指標改變實參一樣,但兩種機制完全不同,引用並沒有另開闢其它空間,直接對「原本」進行了操作,節省了時間和空間。
(拓)結構體陣列作函式引數
用結構體陣列作函式引數包含兩類情況:結構體陣列元素作實參和結構體陣列名作實參。兩類情況仍然服從資料的單向傳遞原則只不過前者傳給形參的是某些變數的值,後者傳給形參的是結構體陣列的首位址。
1.結構體陣列元素作實參
符合結構體變數作實參規則,採取單向「值傳遞」方式將結構體變數所佔的記憶體單元的內容全部順序複製給形參(函式呼叫期間形參也要占用記憶體單元)。注意當實參的成員中包含陣列時形參相應的成員接受到的是乙個位址。
2.結構體陣列名實參
同整形陣列陣列名作實參一樣傳遞給形參的是記憶體中已指定單元的位址,呼叫過程中形引數組與實參陣列占用同一段記憶體單元,因此對形引數組的操作也就是對實參陣列的操作。對陣列的操作表現為雙向性。
綜上所述,對於有參函式呼叫時,實參變數與形參變數之間的資料都是單向的「值傳遞」方式。至於呼叫過程中是否會改變主調函式中變數的值,則只需根據具體演算法看被調函式是否會找到主調函式中變數所在記憶體單元並對其原本進行操作。
c 呼叫c語言dll,形參有char
c 呼叫c語言dll,形參有char 無法獲得char 內容。但是在c 中呼叫dll無問題。說明dll正確,c 中 有問題。直接解決方法 未解決,dll沒問題,就是呼叫後儲存在webtoken中讀取有問題,求大神告知解決方法 變相解決方法 修改dll檔案,將形參char 作為返回值char 返回。原...
c 中 函式作為引數 呼叫時型別問題
最近在學習c 發現了乙個問題,當乙個函式作為另乙個函式引數傳入時,引數型別很有意思 void a void b void m int main 說明形參為void m 時,實際上傳入的實參應為void 型別 函式指標 void 型別代表的是乙個返回值為void的函式,所以實參應傳入乙個函式的位址,而...
C語言函式引數呼叫順序
浩然君前幾天發過乙個小檔案 關於函式引數的呼叫順序的 int arr int ptr arr ptr 123 printf d d ptr,ptr 輸出 8 8 函式引數入棧的順序,一般vc的編譯器是從右往左入棧,那麼這個運算也自然是從右往左。ptr之後ptr再次向後乙個位置移動,即a 2 8。前面...