1.数组指针:指向数组的指针
数组的特点:定义相同类型的若干个元素,元素的地址空间连续,数组名是数组的首元素地址,也是整个数组的首地址;
指针指向一维数组:
指针定义:指针指向空间的数据类型 *变量名;
int num[6]={1,2,3,4,5,6};
int *p=num;//单独的数组名仅仅表示首元素地址,p指向首元素,所以指针指向的空间类型就是首元素类型;
p:存放的是首元素地址-->数据类型为int,故*前面的数据类型为int
*p:得到是num[0]即1;
P+1:以int(四字节)为单位+1,存放的是num[1]的地址;
*(p+1):得到num[1]的内容,即2;
数组取元素可以表示为:num[4]=*(p+4)=*(num+4)=p[4]
在库函数中指针的应用:
strlen();
strlen(char *s);
例:
char buf[32]={“hello”};
char *p=NULL;//0地址
p=buf;//buf数组名表示数组首元素地址=&buf[0]
scanf(“%s”,buf);//利用buf首地址打印
printf(“%s”,p);
区别:
单独的数组名num:表示首元素地址
&数组名&num:表示整个数组的首地址(很少用!)
%p 打印 num 和&num 数值一样。区别在于:
&num+1以 int [6]为单位+1(24字节4*6);num+1以元素大小即int为单位+1(四字节)。
指针指向二维数组:
指针定义:指针指向的空间的数据类型 *变量名;
int num[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int (*p)[4]=num;// 单独的数组名仅仅表示首元素地址,p指向首元素,p指向空间的数据类型就是首元素类型;二维数组的首元素为 num[0],类型是int [4],因此p指向的空间数据类型就是int [4],即int [4]*p转换格式就变成int (*p)[4];
p的数据类型为:int *[4]; p指向的空间的数据类型:int [4]
数组取元素:num[i][j]=p[i][j]=*(*(p+i)+j)=*(*(num+i)+j)
2.指针数组:数组的元素是指针
数组:元素的数据类型 变量名[元素个数];
char *s[4]={“hello”,“base”,“123”,“world”};
s[0]: char *s[0]是“hello”字符串的首地址;
……
s[3]: char *s[3]是“world”字符串的首地址;
char *s[4]={“hello”,“dbase”,“123”,“world”};
s[0]: char *s[0]是“hello”字符串的首地址;
……
s[3]: char *s[3]是“world”字符串的首地址;
3.C语言的五大区:
栈区:局部变量(自动开辟,自动释放);
堆区:预留给开发人员,需要手动开辟malloc手动释放 free;
全局区/静态区:全局变量和静态变量(static)
常量区:存放常量,不能改变的量;(主要)
代码段:存放二进制代码
char buf[32]={“hello”};//局部变量,hello定义在栈区
char *p=buf;//可以通过*p更改字符串;
char *p=“hello”;hello定义在常量区,常量区不能修改;*p不能修改内容
4. const:只读
含义:修饰变量,使其只读;位置:定义变量的时候
1.const int num=100;// const修饰num,num只读,num不能更改;
2.int num=100;
const int *p=#// const修饰*p,仅仅不能通过p来修改p指向的空间的内容;
3.int num = 100;
int const *p = #//同2
4.int num = 100, a = 200;
int *const p = # //const 修饰 p, p 的指向不能改变
p = &a; //报错
5.int num = 100, a = 200;
const int *const p = #
第一个const修饰*p:不能通过p改变p指向空间的内容;第二个const修饰p,p的指向不能改变;
(个人学习总结,理解不够全面,可能存在错误)