二维数组数和指针操作的理解

#include<string.h>
#include <stdio.h> 
int main(void)
{
	int a[4][2] = { { 2,4 },{ 6,8 },{ 1,3 },{ 5,7 } };
	char *p[5] = { "acvsadf", "cwerqwenn", "tttttt" };//字符串指针数组
	int c[4] = { 0,1,2,3 };
	int *ptr = c;
	/*
	这个正确,说明a[0]是一个地址,而且只指向一个int类型;
	也说明它是一维数组(这个数组有两个元素,即2和4)的首元素(这里是2)的地址;
	+1会加上4个字节,即一个int类型的大小;
	*/
	int *p1 = a[0];
	//int (*p2)[2] = a[0];//error
	

	/*
	这个正确,说明&a[0]是一个地址,而且指向一个包含两个int元素的数组;
	也说明它是数组(这个数组有4个元素,分别{ 2,4 },{ 6,8 },{ 1,3 },{ 5,7 })首元素(这里是{2,4})的地址;
	+1会加上8个字节,即两个int类型的大小;
	*/
	int(*p3)[2] = &a[0];//[]表示的是该指针指向数组,而数组里面有[?]个元素
	int(*p4)[2] = a;//这个说明&a[0]和a性质是一样的。
	//int (*p5)[8] = &a;//error
	//int (*p6)[4] = &a;//error
	
	
	//int* p7 = &a;//怎样指向整个数组?
	int* p8 = (int*)a;//这样就达到了对整个数组的访问,这种访问方式和访问一维数组无异。

	printf("数组名操作:\n");
	printf("1------------\n");//这些地址是一样的
	printf("%p\n", a);
	printf("%p\n", &a[0]);
	printf("%p\n", a[0]);	
	printf("%p\n", &a);
	
	printf("2------------\n");//a,&a[0]
	printf("%p\n", a + 1);//a表示数组(退化为1维数组,看做有4个元素)的首元素地址,这里的元素指{2,4},+1会加上8个字节
	printf("%p\n", &a[0] + 1);//这里&a[0]和a的性质一样
	printf("%p\n", &a[1][0]);
	
	printf("3------------\n");//a[0]
	printf("%p\n", a[0] + 1);//这里a[0]表示一维数组(这个数组有两个元素,即2和4)的首元素的地址,+1会加上4个字节
	printf("%p\n", &a[0][1]);
	
	printf("4------------\n");//&a
	printf("%p\n", &a + 1);//这里&a表示整个数组的首地址,+1会加上8*4=32个字节

	printf("5------------\n");
	printf("%d\n", a[0]); //a[0]为啥不是a[0][0]的值?因为它仅是指针,是a[0][0]的地址
	printf("%d\n", *a[0]);//*a[0]表示的是a[0][0]
	printf("%d\n", **a);  //*a表示a[0](因为从前面可知a表示&a[0]),**a表示a[0][0]
	printf("%d\n", a[0][0]);

	printf("\n指针操作:\n");
	printf("%p\n", p1 + 1);//和3一样
	printf("%p\n", p3 + 1);//和2一样
	printf("%p\n", p4 + 1);//和2一样

	//char *p[5] = { "acvsadf", "cwerqwenn", "tttttt" };//字符串指针数组
	printf("\n字符串指针数组操作:\n");
	
	/*
	首先明确这里的p和&p[0]性质一样,则*p即为p[0];
	p+1即为&p[0]+1,也就是&p[1],则*(p+1)即为p[1];
    &p[0]可以看做是一个指向一个数组的指针,+1要加上整个数组的大小。
	*/
	printf("p               = %s\n", p); //乱码
	printf("*p              = %s\n", *p); //"acvsadf"
	printf("(*p)+1          = %s\n", (*p) + 1);//"cvsadf",*p即为p[0],p[0]是指向char类型的指针,因此+1是移动一个char长度单位
    printf("p[0]+1          = %s\n",  p[0]+1); //"cvsadf",和上面一个应该一样
	printf("*(p+1)+1        = %s\n",  *(p+1)+1);//“werqwenn”
	printf("*(p + 1)        = %s\n", *(p + 1));//“cwerqwenn”,注意这里是一个指针,因此是%s打印
	printf("**(p + 1)       = %c\n", **(p + 1)); //‘c’,注意这里已经是完全解引用了,因此是%c打印得到一个字符
	printf("*(p[1] + 1)     = %c\n", *(p[1] + 1)); //‘w’
	printf("*(*(p + 1) + 1) = %c\n", *(*(p + 1) + 1));//'w',注意这里已经是完全解引用了,因此是%c打印得到一个字符


	/*
	int c[4] = { 0,1,2,3 };
	int *ptr = c;
	*/
	printf("\n一维数组的操作:\n");
	printf("1-------------\n");//地址都一样
	printf("&c   = %p\n", &c); 
	printf("c     = %p\n", c);
	printf("&c[0] = %p\n", &c[0]);

	printf("2-------------\n");
	printf("&c    = %d\n", &c);
	printf("c     = %d\n", c);
	printf("&c[0] = %d\n", &c[0]);

	printf("3-------------\n");
	printf("&c+1    = %p\n", &c+1);//&c表示整个数组的开始地址,+1的话,会跨越整个数组
	printf("c+1     = %p\n", c+1);//c和&c[0]性质一样,都表示首元素的地址
	printf("&c[0]+1 = %p\n", &c[0]+1);//后两个应该一样

	printf("4-------------\n");
	printf("*ptr     = %d\n", *ptr);//0
	printf("*(ptr+1) = %d\n", *(ptr+1));//1
	printf("c[0]     = %d\n", c[0]);//0

	getchar();
	return 0;
	
}

 

 

 

 

综上记忆为:统一性,即首字母和“&首元素”意义是一样的。

 

对于int c[4],c和&c[0]是一样的;

 

  • 解引用后,*c=c[0],表示数组第一个元素的值;
  • &c[0]+1和c+1是一样的,都表示c[1]的地址,即&c[1];

 

对于int a[4][2],a和&a[0]是一样的;

 

  • 解引用后,*a=a[0],a[0]表示指向一维数组的指针,可以有指针的操作a[0]+1(此时的a[0]相当于指针,摈弃以前的惯性思维),即a[0][1]的地址&a[0][1];
  • &a[0]+1和a+1是一样的,都表示a[1]的地址,即&a[1];
  • 而a[1]本身就是a[1][0]的地址;
  • 因此由a[1][0]=*a[1]=*(a+1)=*(&a[0]+1);

 

对于char* p[5],p和&p[0]是一样的。

 

  • 解引用后,*p=p[0],p[0]表示指向字符串的指针,可以有指针操作p[0]+1,也可以写成p[0][1],这就和二维数组一致了。
  • &p[0]+1和p+1是一样的,都表示p[1]的地址,即&p[1];
  • *(p+1)=*(&p[1])=p[1],而p[1]在此表示一个字符串指针。
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天糊土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值