1.指针和数组
数组指针 -- 指向数组的指针。
指针数组 -- 数组的元素都是指针。
换句话理解就是:数组指针就是个指针,指针数组就是个数组。
1.1数组指针
数组指针:指向数组的指针;
先回顾一下数组的特点:
1.相同数据类型的若干个元素2.元素的地址空间连续
3.数组名是数组的首元素地址,也是整个数组的首地址。
1.1.1 指针指向一维数组
int num[6]={1,2,3,4,5,6};
先定义一个整形的数组名字为num,其中有6个元素。
回顾一下指针的定义: 指针指向的空间类型 *变量名
int *P=num; 单独的数组名仅仅表示首元素的地址,p指向首元素,所以指针指向的空间数据类型就是首元素类型。
举例说明:
int num[6] = {1,2,3,4,5,6}int *p =num;
p:存放的是首元素的地址; *p得到的是num[0];
在这里我的理解就是,指针指向的是数组的首元素,也就是存放的是首元素的地址,而使用*号就是对这个指针进行解码操作,得到里面的信息,也就是对应数数组的第一个元素num[0].
p的数据类型是:int *。
我的理解就是:根据定义,p指针指向的空间类型,换句话说就是,指针p后面跟的是谁,它是什么数据类型,那么p所指向的数据类型就是什么,那为什么p的数据类型是int *?因为更具数据类型判断的定义,去掉变量名剩下的全是数据类型所以是int *
p+1操作,是以int为单位的+1,一个int是四个字节。 *(p+3)得到的就是num[3]:4。
那为什么会是这样的了?p指针是指向地址,p的偏移是在对应地址空间中进行,回顾指针的定义,指针元素是具有连续性。也就是说在现在这个存储的num[6]数组中,第0个元素和第一个元素之间是相差四个字节的,也就可以推出,当p以int为单位偏移3时,移动的是12个字节,每两个元素之间但是相差4字节。所以在对(p+3)进行解码时得到的是num[3]。
同理在进行数组取元素:num[4] = *(p+4) *(num+4)==num[4] p[4]==*(p+4)
在库函数中指针的应用:
strlen(数组名); //数组名是首元素地址
strlen(char *s);
举例:
#include<stdio.h>
#include <string.h>
int main()
{char buf[32] = {"hello"};char *p = NULL;p = buf; //buf -- 首元素地址 &buf[0]scanf("%s",buf); //buf 是首元素地址这个性质printf("%s",p);return 0;
}
运行结果为你随意输入,然后输入的内容中会被指针p指向首元素地址,然后从这里开始依次写入。
补充:
int num[6] = {1,2,3,4,5,6};
int(*p)[6]=#
其中&num是整个数组的首地址,p指向的空间类型就是整个数组的类型。
p:指针 int(*)[6]
p指向的空间类型:int[6]
p+1 以6个int为单位+1
总结: int num[6];
单独的数组名, num: 表示首元素地址
&数组名, &num: 表示整个数组的首地址 ( 很少用! )
区别:
%p 打印 num 和&num 数值一样
区别在于: &num+1 以 int [6] 为单位+1
num + 1 以元素大小即 int 为单位+1
1.1.2指针指向二维数组
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]
打印 7: num[1][2] *(*(p+1)+2) p[1][2] *(*(num+1)+2)
通式:
num[i][j] *(*(p+i)+j) p[i][j] *(*(num+i)+j)
1.2 指针数组
指针数组:数组的元素全是指针。
数值:元素的数据类型 变量名[元素个数];
举例说明:
char *s[4]={“hello”,“dbase”,“123”,“world”
s[0]: char * “hello”的首地址
s[1]: char * “dbase”的首地址
。 。 。
定义指针:指针指向数组,一维数组
指针指向的空间类型 *变量名;
char **p=s;//s数组名,数组的首地址。
p指向数组的首元素,数组的首元素是char*
指针指向的空间类型就是char*;
代码示例:
#include<stdio.h>
int main()
{char*a[]={"Pascal","Clanguage","dBase","Coble"};char (**p);int j;p = a + 3;for(j = 3; j >= 0; j--)printf("%s\n", *(p--));}
运行结果为:
数组的元素是指针: char * ptr[5] = {NULL};
这个一般用的不多,就不多介绍了。
2 C语言的五大区
栈区: 局部变量(自动开辟, 自动释放);
堆区: 预留给开发人员, 需要手动开辟 malloc, 手动释放 free;
全局区/静态区: 全局变量和静态变量(static)
常量区: 存放常量, 不能改变的量;
代码段: 存放二进制代码
3. 总结指针的定义
1--》 char *p = NULL;
2--》 char ch;
char *p = &ch;
3--》 char buf[32] = {“hello”};//局部变量--“ hello” 栈区
char *p = buf;
小写的 e 改为 E
buf[1] = ‘E’ *(p+1)=’E’;
4--》 用字符串初始化一个指针
char *p = “hello”;//局部变量 -- p 有空间, 8 字节
//p 里面存放的是常量区”hello”的首地址
*( p+1) 打印出 ‘ e’
想小写的 e 改为 E *(p+1)=’E’; //报错, 常量区不能被修改
5--》 char buf[3][80] = {0};
char (*p)[80] = buf;
4 const
含义: 修饰变量, 使其只读
位置: 定义变量的时候
1--> const int num = 100; //const 修饰 num, num 只读
num = 200;//报错
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 的指向不能改变;
关于指针的内容就分享到这里,其中大多数是我自己的理解如果有错误的地方,请在评论区指出。
今天依旧分享一张图片当结束吧。