2021-5-14C语言指针和数组小陷阱for小白

本文有关数组和指针的一些迷惑行为,并进行阐述。

文章目录


问题

  1. 取地址符号在数组前面使用代表什么?
  2. 指向二维数组的二级指针为什么不能二次解引用,而是经过一次解引用就可以得到首元素的值了?
  3. 取地址后进行数值运算,和普通的指针进行运算有什么不同?

解决

数组名是第一个元素的地址,不能说数组名是一个指针,数组名在编译阶段会被替换为,数组第一个元素的首地址,一串二进制数,同时,数组名可以理解为在常量区,因为他是不可更改的。
对于一维数组,数组名就是普普通通的第一个元素的地址,对其进行算数加减运算,都是增加sizeof(基本类型)的长度倍数。
而对于二维数组,数组名不仅仅是普通的第一个元素的地址,C语言还让他代表第一维度的全体地址,虽然这个地址的大小和首元素地址大小相同,但是进行算数加减操作,偏移量是整个维度的倍数。

#include <stdio.h>

int main()
{
	int a[2][5] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = a;
	printf("%d\n", p);
	printf("%d\n", a);
	printf("%d\n", p+1);
	printf("%d\n", a+1);
	return 0;
}

在这里插入图片描述
可以看到第二行和第三行的大小,说明了这一点。

但是如果将a赋值给一个指针类型,这相当于进行了一个隐式转换,转换为了int *类型,为什么这么说呢,因为这样破坏了a进行运算的方式,如果你进行算数操作,如图第一行和第二行的输出,你就知道,这个时候进行+1操作,只仅仅便宜一个int类型长度。并没有偏移二维数组一个行的长度。

对于一维数组这种简单情况,我们考虑一下对数组名进行取地址。

#include <stdio.h>

int main()
{
	int a[5] = { 1,2,3,4,5 };
	int* p = a;
	printf("%d\n", p);
	printf("%d\n", a);
	printf("%d\n", &p);
	printf("%d\n", &a);
	printf("%d\n", a + 1);  //这里不能&(a+1), 谁能帮我从更深入的讲解一下
	printf("%d\n", &a+1); //取地址运算符,优先级最高
	return 0;
}





在这里插入图片描述

可以看到第二行和第四行的数值是一样的,但是进行运算之后数值是不一样的。
说到这儿,就已经解决了上面的三个问题,第一个问题,数组名取地址,因为它并不是一个真正的变量,a会在编译阶段标记为数组元素首地址,这样的一串数字。当然了这串地址所指向的空间,是可以进行改变的。因为数组开辟了一堆空间,空间内的值可以改变。从不可以&(a+1)操作就可以看出,a是在编译期间进行操作的,如果&a连载一起就把首元素地址当成整个元素地址进行操作。

第二问,二次解引用:

#include <stdio.h>

int main()
{
	int a[2][5] = { 1,2,3,4,5 ,6,7,8,9,10};
	int** p = a;
	printf("%d\n", p);
	printf("%d\n", a);
	printf("%d\n", *p);
	printf("%d\n", *a);
	printf("%d\n", p+1);
	printf("%d\n", a+1);
	//printf("%d\n", **p);报错
	printf("%d\n", **a);
	return 0;
}

在这里插入图片描述

在这里,把a赋值给int类型的变量也发生了隐式类型转化,a表示第一个维度的整个地址,数值上为数组首元素地址。它+1等于整个维度偏移,而赋值给int 只能进行int** 类型的偏移,指针类型进行加减操作,只能偏移基本类型的倍数,这里的基本类型是int**,但实际上和int*一样,只不过是个套娃指针。上面程序有所展示,不详细介绍了。

第三问。。。已经说完了

也正是因为*取地址运算符只能对指针使用,所以,才有了多级指针(我之前考虑能不能一个指针多次解引用,发现不行)。

总结

推荐个博客,我觉得写的挺好 链接: [链接](https://www.cnblogs.com/caiminfeng/p/4858032.html). 阎王出告示——鬼话连篇
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值