一篇博客让你搞懂所有指针、数组问题

!!!温馨提示:本篇博客有大量实例,掌握这些,你将对指针和数组以及他们之间的关系有更深一层的理解,建议大家收藏反复观看,多加练习

*本章所运行的结果均在X86环境下,X64自行转换*

指针与数组实例

一维数组

我们先定义一个一维数组int a[ ] = {1,2,3,4};

printf("%d\n",sizeof(a));
这里数组名代表整个数组,计算的是整个数组的大小,所以是4*4=16
printf("%d\n",sizeof(a+0));
这里sizeof里面放的并不是数组名,也就不是整个数组,所以这里的a就是数组首元素的地址,而a+0也还是首元素地址,所以大小就是4
printf("%d\n",sizeof(*a));
*a既是数组的首元素,大小就是4个字节
printf("%d\n",sizeof(a+1));
数组名是首元素地址,a+1即是第二个元素的地址,所以大小为4个字节
printf("%d\n",sizeof(a[1]));
第二个元素大小4个字节
printf("%d\n",sizeof(&a));
&a是数组的地址,但其本质还是地址,是地址就是4个字节
printf("%d\n",sizeof(*&a));
这段代码其实等价于---sizeof(a),所以就是16个字节
printf("%d\n",sizeof(&a+1));
&a+1相当于跳过一个数组,但是它还是地址,也是4个字节
printf("%d\n",sizeof(&a[0]));
首元素地址,4个字节
printf("%d\n",sizeof(&a[0]+1));
&a[0]+1就是第二个元素的地址,是地址就是4个字节

字符数组

我们再定义一个一维数组char a[] = {‘a’,‘b’,‘c’,‘d’,‘e’,‘f’};

在讲解之前,复习一下字符数组的知识,首先我们要明确,在我们以这种形式定义的字符数组中,只放置了abcdef六个字符

printf("%d\n", sizeof(a));
数组名单独放在sizeof内部,这里的a表示整个数组,计算的是整个数组的大小,总共6个字节
printf("%d\n", sizeof(a+0));
a表示数组首元素地址,a+0还是数组首元素地址,那地址就是4个字节

不要在门缝里看指针把指针看遍,不能因为是字符的地址就把它看扁,地址生来平等,也一样是4个字节

printf("%d\n", sizeof(*a));
a表示首元素地址,*a就是首元素,大小是一个字节
printf("%d\n", sizeof(a[1]));
就是数组第二个元素,大小为1个字节
printf("%d\n", sizeof(&a));
虽然是数组的地址,但是地址也是地址,大小为4个字节
printf("%d\n", sizeof(&a+1));
&a+1跳过整个数组的地址,但还是地址,地址就是4个字节
printf("%d\n", sizeof(&a[0]+1));
首元素地址+1是第二个元素的地址,是4个字节

在这里插入图片描述
在这里插入图片描述strlen是求字符串长度的,统计的是在、0之前的字符的个数

printf("%d\n", strlen(a));
因为字符数组中没有\0,所以会一直往后找,产生结果是随机值
printf("%d\n", strlen(a+0));
a+0是首元素地址,与第一种情况一样,都是随机值
printf("%d\n", strlen(*a));
给strlen传过去的需要的是地址,a是数组首元素的地址,*a就是97,那访问97的地址处,非法访问!
printf("%d\n", strlen(a[1]));
跟上面一样,传了b的ASCII值,也是非法访问
printf("%d\n", strlen(&a));
&a类型是char(*)[6],但是传给strlen之后统统变成const char*str,&a是数组的地址,数组的地址和首元素地址是一样的,那么传递给strlen函数后,依然从数组第一个元素开始往后统计,结果是随机值
printf("%d\n", strlen(&a+1));
&a+1跳过这个数组向后数,后面结果为止,所以是随机值
printf("%d\n", strlen(&a[0]+1));
&a+1是第二个元素的地址,但其实是跳过一个数组元素向后找,结果也是随机值

我们再定义一个一维数组char arr[] = “abcdef”;

printf("%d\n", sizeof(a));
数组内有7char类型元素,大小是7
printf("%d\n", sizeof(a+0));
a+0是首元素地址,地址大小为4个字节
printf("%d\n", sizeof(*a));
*a就是首元素,首元素大小为1字节
printf("%d\n", sizeof(a[1]));
第二个元素,1个字节
printf("%d\n", sizeof(&a));
&a是数组地址,地址为4个字节
printf("%d\n", sizeof(&a+1));
&a+1是跳过一个数组的地址,但是还是地址,大小为4个字节
printf("%d\n", sizeof(&a[0]+1));
第二个元素的地址,大小为4个字节

在这里插入图片描述

printf("%d\n", strlen(a));
数组在\0之前有6个字符,所以是6个字节
printf("%d\n", strlen(a+0));
a+0相当于a,大小为6个字节
printf("%d\n", strlen(*a));
*a是字符a,结果出错
printf("%d\n", strlen(a[1]));
数组地址就是首元素地址,从首元素开始向后查找,大小为6个字节
printf("%d\n", strlen(&a));
跳过数组地址向后找,结果未知
printf("%d\n", strlen(&a+1));
&a+1是跳过一个数组的地址,大小为4个字节
printf("%d\n", strlen(&a[0]+1));
&a+1是从第二个元素开始向后找,大小为5个字节

定义一个指针char * p = “abcdef”;

printf("%d\n", sizeof(p));
p指向第一个字节,大小是4个字节
printf("%d\n", sizeof(p+1));
p+1是字符b的地址,大小是4个字节
printf("%d\n", sizeof(*p));
*p就是字符a,大小是1个字节
printf("%d\n", sizeof(p[0]));
p[0]实际上等价于*(p+0),也就是*p,所以大小为1个字节
printf("%d\n", sizeof(&p));
&p是地址,地址是4个字节
printf("%d\n", sizeof(&p+1));
&p+1跳过一个char*的地址,&p是一个变量的地址,+1即跳过一个变量的地址,大小为4个字节
printf("%d\n", sizeof(&p[0]+1));
得到字符b的地址,大小为4个字节

在这里插入图片描述

printf("%d\n", strlen(p));
p内是a的地址,从a向后数所以大小为6个字节
printf("%d\n", strlen(p+1));
p+1是b的地址,从b向后数,大小为5个字节
printf("%d\n", strlen(*p));
*p是字符a,将a作为地址传过去,最后结果出现错误
printf("%d\n", strlen(p[0]));
p[0]是第一个字符a,最后结果错误
printf("%d\n", strlen(&p));
&p就是一个地址,从一个地址向后走,结果我们未知,所以是随机值
printf("%d\n", strlen(&p+1));
遇上一个情况相同,跳过上面的一个地址,向后走,结果还是随机值
printf("%d\n", strlen(&p[0]+1));
&p[0]+1是b的地址,从b向后数,大小就是5个字节

二维数组

定义一个二维数组int a[3][4] = {0};

printf("%d\n",sizeof(a));
数组名单独放在sizeof内部,二维数组a的大小3*4*4=48
printf("%d\n",sizeof(a[0][0]));
00列元素,大小为4个字节
printf("%d\n",sizeof(a[0]));
对于二维数组来说
a[0]就是第一行这个一维数组的数组名
a[1]就是第二行这个一维数组的数组名
a[2]就是第三行这个一维数组的数组名
因此,a[0]是数组名单独放在sizeof内部,计算“整个数组”大小,大小为16个字节
printf("%d\n",sizeof(a[0]+1));
a[0]是第一行数组名,没有单独放在sizeof内部,a[0]表示数组首元素地址,也就是a[0][0]的地址,所以a[0]+1是第一行第二个元素的地址,是地址就是4个字节。
printf("%d\n",sizeof(*(a[0]+1)));
计算的第一行第二个元素的大小,大小为4个字节
printf("%d\n",sizeof(a+1));
a是数组首元素的地址,是第一行的地址,a+1指向第二行,但是地址的大小就是4个字节
printf("%d\n",sizeof(*(a+1)));
*(a+1)等价于a[1],即sizeof(a[1])就是第二行的大小,16个字节
printf("%d\n",sizeof(&a[0]+1));
取出第一行地址,+1是第二行地址,地址大小为4个字节
printf("%d\n",sizeof(*(&a[0]+1)));
&a[0]是第一行的地址,&a[0]+1是第二行的地址,*(a[0]+1)计算的是第二行的大小
printf("%d\n",sizeof(*a));
a是数组首元素地址,*a就是第一行,则计算第一行的大小,16个字节
printf("%d\n",sizeof(a[3]));
虽然越界了,但是我们不会真的去访问这段内存,只计算这个一维数组的大小,16个字节

看到这里本章就结束了伟大的程序员辛苦了在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值