数组知识(含思维导图)

本文不涉及非常基础知识,但会提及经常出错的地方,知识点;
在这里插入图片描述
数组名:在一般情况下代表数组首元素地址,有两个例外一是sizeof(数组名)和 &数组名,此时这两种数组名的使用代表整个数组;
一、整型数组
注释:以下如有4/8这是运行平台不同,32位为4字节,64位为8字节;
大家思考以下代码打印的值(单位:字节);

#include<stdio.h>
int main()
{
	int a[] = {1,2,3,4};
	printf("%d\n",sizeof(a));
	//16---计算整个数组所占空间的大小
	printf("%d\n",sizeof(a+0));
	// 4/8---a代表首元素地址加零还是首元素地址,地址为4/8个字节
	printf("%d\n",sizeof(*a));
	//4---a代表首元素地址(*a)就是首元素,计算首元素所占空间
	printf("%d\n",sizeof(a+1));
	//4/8---a+1指向第二个元素地址
	printf("%d\n",sizeof(a[1]));
	//4---计算第二个元素所占空间
	printf("%d\n",sizeof(&a));
	//4/8---&a取出整个数组的地址,地址为4/8个字节
	printf("%d\n",sizeof(*&a));
	//16---(*&a)=(a)这两个效果相同
	printf("%d\n",sizeof(&a+1));
	//4/8---&a取出数组地址加1跳过整个数组
	//指向数组最后一个元素的下一个元素的地址
	//此处存在越界这里只是讲&a+1指向哪里
	printf("%d\n",sizeof(&a[0]));
	//4/8---第一个元素地址,地址为4/8个字节
	printf("%d\n",sizeof(&a[0]+1));
	//4/8---指向第二个元素的地址,地址为4/8个字节
	return 0;
}

二、字符数组
思考以下代码的值(单位:字节);

#include<stdio.h>
int main()
{
	//strlen寻找'\0'为结尾
	char arr[] = {'a','b','c','d','e','f'};
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr+0));
	printf("%d\n", strlen(&arr));
	//以上三个为随机值且相同,都是将arr地址交给strlen();
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	//以上两句都为错误语句;strlen参数必须为地址;
	//*arr取到arr数组第一个元素'a',将'a'传进strlen函数,
	//strlen函数认为这个'a'为查找起始地址,
	//此时a将转换为97则会从地址为97开始访问,但此时已经非法访问
	return 0;
}

三、二维数组
二维数组的数组名是首元素地址,此时首元素地址为第一行地址;
思考以下代码的值(单位:字节);

#include<stdio.h>
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof( a ));
	//48---计算整个数组的大小
	printf("%d\n", sizeof( a[0][0] ));
	//4---计算数组第一行第一个元素所占空间
	printf("%d\n", sizeof( a[0]) );
	//16---a[0]表示第一行,所以计算的是第一行所占空间的大小
	printf("%d\n", sizeof( a[0]+1) );
	//4/8---a[0]表示第一行,相当于数组名,数组名就是首元素地址
	//所以加1就是第一行第二个元素的地址
	printf("%d\n", sizeof( *(a[0]+1) ));
	//4---a[0]+1表示第一行第二个元素的地址
	printf("%d\n", sizeof( a+1 ));
	//4/8-a是首元素地址加1指向第二行的地址,此时把二维数组抽象成一位数组
	printf("%d\n", sizeof( *(a+1) ));
	//16---a+1表示第二行地址,(*a+1)计算第二行元素所占空间
	printf("%d\n", sizeof( &a[0]+1 ));
	//4/8---&a[0]表示第一行地址,加1指向第二行地址
	printf("%d\n", sizeof( *(&a[0]+1) ));
	//16---&a[0]+1表示第二行地址,
	//*(&a[0]+1)取出第二行,即计算第二行元素所占空间
	printf("%d\n", sizeof( *a ));
	//16---a表示首元素地址,即第一行地址*a计算第一行元素所占空间
	printf("%d\n", sizeof( a[3] ));
	//16---计算第四行所占空间,但此时已非法访问;
	//注意:sizeof函数不会真实去访问内存
	return 0;
}

以下是以下题目(大家认真思考哦):
第一题:

#include<stdio.h>
struct Test
{
	int Num;
	int *pcName;
	short sDate;
}
//假设p的值为0x100000,struct Test类型变量大小20字节;
int main()
{
	p = (struct Test*)0x100000;
	printf("%p\n",p+1);//0x00100014
	//指针加一,这个一代表多少取决于指针类型
	printf("%p\n",(unsigned long) p+1);//0x00100001
	//将p存储内容强制转换为unsigned long再加1
	printf("%p\n",(unsigned int*) p+1);//0x00100004
	//将p存储内容强制转换为unsigned int*再加1;
}

第二题:

#include<stdio.h>
int main()
{
	int a[4] = { 1, 2, 3, 4};
	int *ptr1 = (int*) ( &a + 1 );
	int *ptr2 = (int*) ( (int)a + 1);
	//将a的存储内容转换为int然后再加1,
	//导致跳过一个字节最后转换为int*的指针;
	printf("%x,%x",ptr1[-1],prt2);//4,2000000(十六进制输出)
	//ptr1[-1]=*(ptr1-1)
	//它跳过一个字节指向途中标记的位置又因为它的数据类型为int访问4字节
	//褐色圈计算ptr2访问的内容,
	return 0;
}

在这里插入图片描述
第三题:

int main()
{
	int a[5][5] = {0};
	int (*p)[4];
	p = a;//p只能指向四个元素,却将a赋值于p
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
	//&a[4][2]---小伙伴肯定能看懂,它表示第五行第三个元素
	//&p[4][2] (是不是看到很懵逼?)
	//先说     p[4] = *( p + 4 )
	//        p[4][2] = *( *(p+4) + 2   (这里式子是互通的)
	//由于p每次只能访问4个int类型元素(如图)
	//两个地址相减等于-4
	//第一个%p 内存存入的是-4的补码,%p是认为这个内容是地址直接打印
	//第二个%d 有符号数,输出-4
	return 0;
}

在这里插入图片描述
最后抛出一道题:(供大家思考,将你的答案留在评论区)

#include<stdio.h>
int main()
{
	char *c[] = {"ENTER", "NEW", "POINT", "FIRST"};
	char *cp[] = {c+3, c+2, c+1, c};
	char ***cppp = cp;
	printf("%s\n", **++cpp);
	printf("%s\n", *--*++cpp+3);
	printf("%s\n", *cpp[-2] + 3);
	printf("%s\n", cpp[-1][-1] + 1);
	return 0;
}

不懂的评论区见哦;
记得三连哦;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值