数组名和指针区别及变化

数组名和指针

数组名和指针都可以通过增减偏移量访问元素。但数组名可以理解为常指针,不能自增自减。数组名赋值给其他指针后,可以通过其他指针操作。
分析如下代码:

#include <iostream>

const char* c[] = { "Welcome", "to", "Beautiful", "Beijing" };
const char** cp[] = { c + 3, c + 2, c + 1, c };
const char*** cpp = cp;

int main()
{
	printf("%d:%s %d:%s %d:%s %d:%s\n", c[0], c[0], c[1], c[1], c[2], c[2], c[3],c[3]);
	printf("%d %d %d %d\n", &c[0], &c[1], &c[2], &c[3]);
	printf("%d %d %d %d\n", cp[0], cp[1], cp[2], cp[3]);
	printf("%d %d %d %d\n", &cp[0], &cp[1], &cp[2], &cp[3]);
	printf("%d %d %d %d\n", cpp, cpp + 1, cpp+2, cpp+3);
	printf("%s\n", **++cpp);			// Beautiful
	printf("%s\n", *-- * ++cpp + 3);	// come
	printf("%s\n", *cpp[-2] + 3);		// jing
	printf("%s\n", cpp[-1][-1] + 1);	// o
	return 0;
}

程序结果如下图:
在这里插入图片描述

数组的[]运算就相当于一次解引用
cpp可以理解为一个遍历cp数组的指针,初始为cp数组第一个元素的首地址
对应的地址结构如下:
在这里插入图片描述

  • 对于**++cpp,相当于cpp=cpp+1,再**cpp。cpp+1后就指向cp数组第二个元素,即此时cpp=&cp[1];*cpp解一重引用后,也是一个指针,即 *cpp=cp[1],而cp[1]存的是c[2]的地址,即cp[1]=&c[2],再解一重引用后,获得c[2]的值,即 *cp[1]=c[2],也就是 **cpp=c[2],而c2就是Beautiful的地址,因此输出Beautiful
  • 此时cpp已经指向了cp数组的第二个元素,即cp[1]。再++cpp后指向cp[2],因此*++cpp就是 cp[2],cp[2]存的是c[1]的地址,也是一个指针;再减一后,指向的就是c数组的第一个元素,,即c[0],解引用后就是c[0]。所以 *-- *++cpp就是c[0],c[0]+3输出就是come
  • cpp此时指向cp数组的第三个元素,cpp[-2]就是cpp指针减2处的元素(cpp不会变),因此cpp[-2]等价于cpp[0](相当于cpp[2-2])。*cpp[-2]=*cp[0]=c[3],也就是Beijing,c[3]+3就输出jing
  • 此时cpp仍指向cp数组的第三个元素,cpp[-1]相当于cp[1],cp[1][-1]相当于c[2]处的指针减一,也就是c[1],即cpp[-1][-1]=cp[1][-1]=c[1],也就是to,c[1]+1就输出o

指针的变化:

数组名代表首元素的地址,+1后访问数组第二个元素。例如a[10]的第二个元素是a[1],a[2][3]的第二个元素是第二行,a[2][3][3]的第二个元素的第二个二维数组。
&数组名代表一个指向整个数组类型的指针,+1会跳过整个数组范围。例如a[2][3],a+1跳过一个2 * 3的数组,a[2][2][3],a+1跳过一个2 * 2 * 3的数组
假设数组
int a[10]; int (*p)[10] = &a;

  • a是数组名,是数组首元素地址,+1表示地址值加上一个int类型的大小,如果a的值是0x00000001,加1操作后变为0x00000005。*(a + 1) = a[1]
  • &a是数组的指针,其类型为int (*)[10](就是前面提到的数组指针),其加1时,系统会认为是数组首地址加上整个数组的偏移(10个int型变量)l,值为数组a尾元素后一个元素的地址。
  • 若(int *)p ,此时输出 *p时,其值为a[0]的值,因为被转为int *类型,解引用时按照int类型大小来读取。
    分析如下代码:
int main() {
	int a[2][2][3] = { {{1,2,3},{4,5,6}},{{7,8,9},{10,11,12}} };
	int* ptr = (int*)(&a + 1);
	printf(" %d %d", *(int*)(a + 1), *(ptr - 1)); // 7 12
	printf(" %d %d", *(int*)(*a + 1), *(int*)(*a + 2)); // 4 7
	// 因为a是三维数组,a是地址,+1跳过一个二维数组;*a仍然是指针,+1跳过一个一维数组
	return 0;
}

在这里插入图片描述
在这里插入图片描述

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值