目录
6.7 指针数组
1、指针和数组的关系
指针可以保存数组元素的地址,那么也可以定义一个数组,数组中有若干个相同类型的指针变量,这个数组成为指针数组,它是若干个相同类型的指针变量构成的集合。
2、定义方法:类型名 * 数组名[元素个数];
int* p[5]; //定义了一个整形的指针数组p,数组名是p,有5个元素,每个元素都是整形指针变量int*,它们分别储存了一个整形数据的地址
int a[5];
p[0] = a;
6.8 指针的指针
指针的指针**p,即指针的地址。我们定义的一个指针变量本身占用4个字节,指针变量也有地址编号,但是类型不同,一个是int*,一个是int**。
int** p表示*p指向的是int*类型数据的地址。无论几层的指针,其占用的存储空间大小都是4个字节。
int a = 0x12345678;
int* p,**p_p;
p = &a; //p中存放的是a的地址编号,p指向a
p_p = &p; //p_p中存放的是p的地址编号,p_p指向p
int main()
{
int a = 5, b = 7;
int* p, ** p_p;
p = &a; //p中储存了a的地址
p_p = & p; //p_p中储存了p的地址
printf("p = %p, *p = %d\n", p,*p);
printf("p_p = %p, *p_p = %p, **p_p = %d\n", p_p,*p_p,**p_p);
return 0;
}
运行的结果是:
p = 006FF8D0, * p = 5
p_p = 006FF8B8, *p_p = 006FF8D0, **p_p = 5
p_p指向p,储存的是p的地址,取p_p指向的值也就是p的地址,再取值也就是a的值了。
6.9 字符串和指针
1、字符串:以\0结尾的若干个字符的集合:比如"helloworld",这个字符串有11个字符,分别是h e l l o w o r l d \0。
字符串的地址就是第一个字符的地址:"helloworld"的地址就是字符串中"h"的地址。
可以定义一个字符指针变量:char* s = "helloworld";
2、字符串的存储形式:数组、文字常量区、堆
(1)字符串存放在数组中
即在内存(栈、静态全局区)中开辟了一段空间来存放字符串。
char strint[100] = "I Love China";
定义了一个字符数组string来存放100个字符,并且用"I Love China"来给数组进行初始化。普通全局数组,内存分配在静态全局区,普通局部数组,内存分配在栈区,静态数组(静态全局数组、静态局部数组),内存分配在静态全局区
(2)字符串存放在文字常量区
在文字常量区开辟了一段空间存放字符串,将字符串的首地址赋给指针变量。
char *str = "I Love China";
str只是保存了"I"的地址,也就是字符串的首地址。而这串字符串存放在文字常量区。
(3)字符串存放在堆区
使用malloc等函数在堆区申请空间,将字符串拷贝到堆区
char* str = (char*)malloc(10*sizeof(char)); //动态申请了10个字节的存储空间,首地址给str赋值
strcpy(str."I Love China"); //将字符串"I Love China"拷贝到str指向的内存里
3、字符串的可修改性
字符串的内容是否可以被修改,取决于字符串存放在哪里
(1)存放在数组中的字符串(数组没有被const修饰),内容可以被修改
char str[100] = "Hello World";
str[2] = Y;
int main()
{
char str[100] = "Hello World";
str[2] = 'Y';
printf("%s", str);
return 0;
}
运行的结果:
HeYlo World
(2)存放在文字常量区的内容不可以被修改
char* str = "I Love China";
*str = 'y';//错误,文字常量区的内容不可以修改
但可以给str重新赋值,让它指向别的内容。
(3)堆区中的内容可以被修改
cahr* str = (char*)malloc(10);
strcpy(str,"I Love China")l
*str = 'y';//正确,堆区中的内容可以被修改
4、初始化
(1)字符数组的初始化
char buf_aver[20] = "Hello Wolrd";
(2)指针指向文字常量区初始化
char *buf_point = "hello world";
(3)指针指向堆区,不能初始化,只能先给指针赋值,让指针指向堆区,再使用strcpy、scanf等方法将字符串拷贝到堆区
char* buf_heap;
buf_heap = (char*)malloc(15);
strcpy(bug_heap,"helloworld");
scanf("%s",buf_heap);
5、使用时赋值
(1)字符数组:使用scanf或strcpy
char buf[20] = "hello world";
buf = "hello kitty"; //错误,因为字符数组的名字是数组的首地址,是个常量,不能给常量赋值
strcpy(buf,"hello kitty"); //正确,使用strcpy函数将"hello kitty"赋给buf数组
scanf("%s",buf); //正确,将键盘输入的字符串赋给buf数组
(2)指针指向文字常量区
char* buf_point = "hello world";
buf_point = "hello kitty"; //正确,这是将buf_point指向了一个新的字符串
strcpy(buf_point,"hello kitty"); //错误,这时buf_point指向文字常量区,不能给常量赋值
(3)指针指向堆区
char* buf_heap;
buf_heap = (char*)malloc(15);
strcpy(buf_heap,"hello kitty");
scanf("%s",buf_heap);
【总结】