值傳遞
在函數調用那一篇裡已經揭開了值傳遞的真相: 實參、形參有各自的存儲空間(實參也可能只是一個值, 而沒有存儲空間),實參 -> 形參是個值拷貝的過程, 在函數調用前完成了這個拷貝過程, 此後如果函數中對形參進行修改,實參的值不會跟著變。
但並不是我們就沒辦法在函數中修改外部變量了, 用指針就好了,我們不需要修改指針的值, 而只是修改指針指向的內存塊:
0重指針(基本類型、結構體)
int add(int a, int b)
{
return a + b;
}
只有這種參數的函數,只需要參數的值,進行計算後返回結果, 不需要修改外部變量。
1重指針
void swap(int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
使用場景:
int a=1, b=2;
swap(&a, &b);
函數中使用 1 重指針一般出於兩種目的:
- 函數中要修改外部 基本類型 或 結構體 的值。
- 為了節省參數空間。假設函數想要讀一個外部的 佔用空間很大的結構體變量,比如有 4KB 大小, 雖然根本沒想改它,但是如果用指針接收它的地址, 參數只佔 4 字節;如果用結構體作為參數, 參數要佔 4KB 的內存,而且還要進行值拷貝! 用 char* 來接收字符串也可以看做是出於節省空間的目的。
2重指針
C 標準庫的頭文件 string.h 中提供了一個 strdup 函數:
char *strdup(char *s);
該函數的作用是複製字符串, 返回的字符串的存儲空間是動態申請的,不是原來字符串的空間。 如果你是第 1 次聽說有這個函數,不要妄自菲薄, 我也是大三下才知道的O(∩_∩)O~
現在不用返回值,用 2 重指針來實現這個函數:
void my_strdup(char **p, char *s)
{
unsigned int len = strlen(s) + 1;
*p = (char *)malloc(len);
memcpy(*p, s, len);
}
使用場景:
char *s = "abc";
char *d = NULL;
my_strdup(&d, s);
從這個例子中可以看出 2 重指針用於需要修改指針的時候, 一般是要在函數中為指針動態地申請空間。 而這一般可用返回指針來實現,但是如果有多個指針要一併修改, 用 2 重指針就要方便很多,因為返回值只有 1 個, 而參數的個數在語法上是沒有限制的。
strdup 返回的字符串用完後不要忘了 free 哦!
另外,一般沒有使用 3 重以上指針作參數的必要。