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;
}
发布了295 篇原创文章 · 获赞 158 · 访问量 101万+

猜你喜欢

转载自blog.csdn.net/kikajack/article/details/90737494