C 語言二級指針的段錯誤

C語言中的指針變量

C 語言中,指針變量也是變量,只不過跟 char、int 型等基本類型變量不同,指針變量中保存的是其他變量的地址和類型。

通過這個地址,並根據類型來讀取指定長度的字節,就可以把這個變量解析出來。

int a = 3;
int *p = &a; // & 是取地址符號,返回變量 a 的地址
printf("%d\n", *p);

C 語言中本身不支持字符串,但是通過 char * 類型的指針可以實現字符串效果:

char *s = "hello world";
printf("%s\n", s);

上面代碼中,創建指針變量 s,指向字符類型的變量。然後把變量 s 的值當做字符串類型來解析,直到碰到字符串結束標誌 \0 就結束讀取。

字符串數組

char *arr[] = {"hello world", "test"};
printf("%s\n", arr[0]);

上面代碼中,先創建數組 arr,數組中的每個元素都是 char * 類型,即指向字符的指針。然後把 arr[0] 數組第一個元素當做字符串解析。

char (*p)[10] = "hello";
printf("%s\n", *p);

二級指針

二級指針跟普通指針變量的區別在於:指針變量直接報錯目標變量的地址,而二級指針變量保存的是另一個指針變量的地址,另一個指針變量才真正保存目標變量的地址。

二級指針的主要用途:

  • 字符串數組
  • main 函數的入參 argv

字符串數組

上面示例用數組的形式實現了字符串數組,在聲明數組的同時初始化。其實還可以用二級指針實現字符串數組。

例如 char **p,聲明的變量 p 就是一個二級指針。p 指向的變量類型是 char *,即字符指針,然後這個字符指針才真正指向一個字符變量。

下面代碼是錯誤的示例,會報錯:segmentation fault。

#include <stdio.h>
#include <malloc.h>

int main () {
    char **p;
    *p = "helo"; // 未分配內存空間就直接使用,報錯
    p[1] = "wold";
    
	printf("%s\n", *p);
	return 0;
}

出現段錯誤的原因是:編譯器會自動爲創建的 char ** 類型的變量 p 分配內存空間。但是,*p 指向的 char * 類型的變量則並沒有分配內存空間,就直接使用了。

只要讓 p 變量指向一塊經過初始化的內存,即可消除錯誤:

#include <stdio.h>
#include <malloc.h>

int main () {
	// 分配內存空間,並將首地址返回給二級指針變量 p
	// 然後用這塊連續內存保存中間指針變量
    char **p = malloc(sizeof(char *) * 2);
    *p = "helo";
    p[1] = "wold";
    
	printf("%s\n", *p);
	return 0;
}

指向數組的指針

一維數組

int a[10];
int *p = a;

二維數組

二維數組不能像一維數組那樣簡單的傳遞指針變量。

二維數組本質上仍是內存中的一塊連續地址空間,只不過人爲的將這塊空間分隔爲固定長度的子空間。

只要確保指針每次加一時,可以跳到下一塊子空間,就可以用指針完美的表示二維數組。char (*p)[n] 就可以實現這個目的,其中 n 是子空間大小。

char (*p)[10] 這裏的括號不能省略,否則 char *p[10],編譯器會從右到左解析,變量 p 解析爲數組,存放 10 個 char * 類型的變量。

#include <stdio.h>

int main () {
	char arr[2][10] = {{"hello"}, {'w'}};
	// 定義指針變量 p,指向有 10 個元素的 char 類型的數組
	char (*p)[10] = arr;
	
	printf("%s\n", *p);
	printf("%s\n", *(p+1));
	
	(*p)[0] = 'a';
	printf("%s\n", *p);
	
	(*(p + 1))[0] = 'a';
	printf("%s\n", *(p+1));
	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章