我正在爲我的一些C庫工作C語言技能。在完成第一個工作實現之後,我現在將通過代碼來使其更高效。目前,我正在通過引用或值傳遞函數參數的主題。爲什麼我會按C中的值傳遞函數參數?
我的問題是,爲什麼我會通過C中的值傳遞任何函數參數?代碼可能看起來更清晰,但是不會總比通過引用傳遞效率更低?
我正在爲我的一些C庫工作C語言技能。在完成第一個工作實現之後,我現在將通過代碼來使其更高效。目前,我正在通過引用或值傳遞函數參數的主題。爲什麼我會按C中的值傳遞函數參數?
我的問題是,爲什麼我會通過C中的值傳遞任何函數參數?代碼可能看起來更清晰,但是不會總比通過引用傳遞效率更低?
在C中,所有參數都是按值傳遞的。一個真正的通過引用傳遞的是當你看到一個修改的,沒有任何明確的間接所有的效果:使用值,而不是指針雖然
void f(int c, int *p) {
c++; // in C you can't change the original paramenter passed like this
p++; // or this
}
,常常需要:
int sum(int a, int b) {
return a + b;
}
你不會寫如:
int sum(int *a, int *b) {
return *a + *b;
}
因爲它不安全,效率低下。效率低下,因爲存在額外的間接性。而且,在C中,指針參數表明調用者將通過指針修改該值(特別是當指針類型的大小小於或等於指針本身時)。
這可能是一個愚蠢的問題,但爲什麼是'''int sum(int * a,int * b){return * a + * b; }'''函數不安全? – c00kiemonster
,因爲那樣你就有了間接指向NULL /懸空指針的風險。 – perreal
調用者現在需要爲a和b創建變量,不能傳遞常量。調用者還必須決定是否需要'malloc'值或傳遞變量的地址,並假定值可能會被修改,因爲它們不是'const'(可能需要複製值)。如果調用者傳遞NULL,未初始化的指針和/或指向無效內存位置的指針,則取消引用指針也不安全。 – Joe
請參閱Passing by reference in C。按引用傳遞是C中的一個用詞不當,它指的是傳遞變量的地址而不是變量,但是您將指針傳遞給值爲的變量。這就是說,如果你要將變量作爲指針傳遞,那麼是的,它會稍微更有效率,但主要原因是能夠修改它指向的原始變量。如果您不希望這樣做,建議您以價值爲目的,以明確您的意圖。
當然,就Cs較重的數據結構之一而言,所有這些都沒有意義。無論你喜不喜歡,數組都通過指向第一個變量的指針傳遞。
感謝**所有**信息**。 – Joe
兩個原因:
很多時候,你將不得不取消引用您在很多時候已經通過指針(認爲長for循環)。你不想每次都想取消引用那個地址的值。直接訪問速度更快。
有時候你想修改函數內部的傳入值,但不是調用者。例如:
void foo(int count){
while (count>0){
printf("%d\n",count);
count--;
}
}
如果你想要做上述的東西按引用傳遞,你會haev創建自己的函數中另一個變量來存儲它第一次。
取消引用變量與直接訪問的性能損失是多少?它是在數量級的土地? – c00kiemonster
它可以是3個週期而不是1個週期。如果您正在編寫一個四核機器,誰在乎(主要)?如果你正在構建任何基於性能的(實時應用程序,嵌入式系統),這可能會產生巨大的差異。 – Phonon
個人資料,個人資料,個人資料!這個答案的第一部分非常具有推測性,並且不考慮編譯器優化。 – Dan
因爲代碼爲計算機編寫下一代人並不重要。如果您傳遞引用,則任何讀者都必須假定任何調用的函數都可以更改其參數的值,並且在調用之前有義務檢查它或複製參數。
你的函數簽名是一個合約,並將你的代碼分開,這樣你就不必將整個代碼庫放入頭部,以便理解某些領域正在發生什麼,通過傳遞引用你正在做的下一個人的生活變得更糟,作爲程序員的最大的工作應該是讓下一個人的生活變得更好 - 因爲下一個人可能會成爲你。
很好的答案。另外,傳遞值實際上可以更快,因爲編譯器知道參數不會互相混淆,因此可能會生成更好的代碼。 – Nemo
「讓下一個人的生活變得更糟」的例子是一個很好的例子,這是我忽略的。 – c00kiemonster
我一直認爲下一個傢伙是一個知道你地址的殺人狂。 –
**每個**參數都通過C中的值傳遞。如果它不大於指針,傳遞一個副本肯定不是那麼低效。 –
更不用說這會是多麼不方便:'int get_int(); void process_int_A(const int x); void process_int_B(const int * const x);'。比較:'void foo(){process_int_A(get_int()); }'''void foo(){const int result = get_int(); process_int_A(結果); }'。爲每個返回值需要明確的中間存儲將是殺手。在C++中這不是一個問題,在那裏你可以綁定到臨時值的「真實」引用。 – GManNickG