【C语言】一次让你看透数组的笔试题

      以下内容含金~

       带你掌握数组名与地址的各种关系,克服畏惧数组的心理 !  


目录

一维数组

解析

字符数组

解析

二维数组

解析


一维数组

        你能做出几道?证明一下自己的实力?

int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a+0));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(a[1]));
printf("%d\n",sizeof(&a));
printf("%d\n",sizeof(*&a));
printf("%d\n",sizeof(&a+1));
printf("%d\n",sizeof(&a[0]));
printf("%d\n",sizeof(&a[0]+1));

解析

int a[] = {1,2,3,4};

printf("%d\n",sizeof(a));

数组名一定是首元素地址吗?

提示一点,只有以下两种情况出现数组名才表示整个数组,其他情况一律表示首元素地址
1.sizeof(数组名);
2.&数组名;

所以这里表示整个数组,因而求的是整个数组的大小,也就是4个整形的大小,答案是16

printf("%d\n",sizeof(a+0));

注意这里,sizeof()内部数组名没有单独出现,故这里表示首元素的地址,地址的大小是多少呢?

答案是4/8(32位平台/64位平台)

printf("%d\n",sizeof(*a));

首元素地址解引用也就是首元素,是一个整形,所以

答案是4

printf("%d\n",sizeof(a+1));

首元素地址+1 = 下一个地址 因为数组中地址是连续的,故指向下一个元素的地址
但他的本质依然是地址哩~ 所以

答案是4/8

printf("%d\n",sizeof(a[1]));

a[1] == *(a + 1);也就是数组的第二个元素,所以

答案是4

printf("%d\n",sizeof(&a));

注意,这里是取出整个数组的地址,但他终究还是是地址阿~ 所以

答案是4/8

printf("%d\n",sizeof(*&a));

打开你的思维
两种理解方式:
1.取出整个数组的地址,再解引用,相当于找到了整个数组,也就是计算整个数组的大小
2.*与&抵消,相当单独将数组名放入sizeof内部

答案是16
printf("%d\n",sizeof(&a+1));

取出整个数组的地址,+1跳过整个数组,但依然是地址,所以

答案是4/8

printf("%d\n",sizeof(&a[0]));

打开你的思维
两种理解方式:
1.a[0]是数组的第一个元素,取出他的地址
2.&a[0] == &*(a + 0); 这里&*抵消,剩下a + 0,也就是首元素的地址

答案是4/8

printf("%d\n",sizeof(&a[0]+1));

取出数组第一个元素的地址,+1跳过一个元素的地址,指向数组第二个元素的地址,终究还是地址~

答案是4/8

值得注意的是

printf("%d\n",sizeof(&a+1));

跳过整个数组指的是 由

 到+1后的操作

 


字符数组

        你能做出几道?证明一下自己的实力?

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));

printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));

printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
char *p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p+1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p+1));
printf("%d\n", sizeof(&p[0]+1));

printf("%d\n", strlen(p));
printf("%d\n", strlen(p+1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p+1));
printf("%d\n", strlen(&p[0]+1));

解析

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));

数组名单独放在sizeof内部,求的是整个数组的大小 所以

答案是6

printf("%d\n", sizeof(arr+0));

数组名没有单独放在sizeof内部,表示首元素地址,首元素地址+0还是首元素地址 所以

答案是4/8

printf("%d\n", sizeof(*arr));

首元素地址解引用,得到首元素,是一个字符'a' 所以

答案是1

printf("%d\n", sizeof(arr[1]));

arr[1]表示数组第二个元素,是字符'b' 所以

答案是1

printf("%d\n", sizeof(&arr));

这里取出整个数组的地址,但依旧是地址~ 所以

答案是4/8

printf("%d\n", sizeof(&arr+1));

取出整个数组的地址,+1跳过整个数组,但依旧是地址~ 所以

答案是4/8

printf("%d\n", sizeof(&arr[0]+1));

取出首元素的地址,+1跳过第一个元素,指向数组第二个元素的地址,所以
答案是4/8

------------------------以下是strlen------------------------------

printf("%d\n", strlen(arr));

将首元素的地址给strlen求字符串长度,到'\0'停止
但是数组中真的有放'\0'吗?
实际上,数组里只存放了abcdef这六个字符
所以strlen会一直找啊找,找啊找,直到找到内存中随机初始化的\0截至

答案是 随机数
printf("%d\n", strlen(arr+0));

首元素地址+0还是首元素地址,数组中没有'\0' 所以

答案是 随机数

printf("%d\n", strlen(*arr));

将首元素放进strlen这算什么呀?
什么都不算,这时一种错误的写法
为什么呢?看一下strlen函数的要求:
size_t strlen( const char *string );
他需要的是一个const的指针

想象一下,将字符'a'强行塞入,经ASCII转换后是97,访问的是97处的地址啊
这是一个位置极低的地址,已经造成了非法访问,如果你有兴趣,编译这段代码
程序走到这里就会挂掉

答案是 error
printf("%d\n", strlen(arr[1]));

这个也是同样的道理,只不过是第二个元素

答案是 error

printf("%d\n", strlen(&arr));

取出整个数组的地址,这可怎么办呢?

大家是否还记得取出首元素的地址和取出整个数组的地址是一样的,因为就算你要一次访问
整个数组,起始位置也一定是首元素地址不是吗?

但闹了半天,却因数组里没有'\0' 所以

答案是 随机数

printf("%d\n", strlen(&arr+1));

取出整个数组的地址,+1跳过整个数组,但内存中未初始化的位置内容都是随机的 所以

答案是 随机数-6

printf("%d\n", strlen(&arr[0]+1));

取出首元素的地址,+1指向第二个元素 所以

答案是 随机数-1
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));

这里arr单独出现在sizeof内部,表示计算整个数组的大小,但要注意哦
这里的字符串里隐藏了一个'\0' 所以

答案是7

printf("%d\n", sizeof(arr+0));

arr没有单独出现在sizeof内部,表示首元素地址 所以

答案是4/8

printf("%d\n", sizeof(*arr));

首元素地址解引用得到数组第一个元素,是字符'a' 所以

答案是1

printf("%d\n", sizeof(arr[1]));

arr[1]表示数组的第二个元素,是字符'b' 所以

答案是1

printf("%d\n", sizeof(&arr));

取出整个数组的地址,但依然是地址 所以

答案是4/8

printf("%d\n", sizeof(&arr+1));

取出整个数组的地址,+1跳过整个数组,但依然是地址, 所以

答案是4/8

printf("%d\n", sizeof(&arr[0]+1));

取出首元素的地址,+1指向第二个元素,但依然是地址~ 所以
答案是4/8

--------------------以下是strlen----------------------------

printf("%d\n", strlen(arr));

strlen读到'\0'停止,这里arr表示首元素的地址,表示从首元素开始读取 所以

答案是6

printf("%d\n", strlen(arr+0));

首元素地址+0还是首元素地址 所以

答案是6

printf("%d\n", strlen(*arr));

首元素地址解引用放入strlen,上面的题解释过,造成了非法访问,这是一种错误写法,所以

答案是error

printf("%d\n", strlen(arr[1]));

arr[1]是首元素和上一题同理 所以

答案是error

printf("%d\n", strlen(&arr));

取出整个数组的地址,整个数组的地址也是从首元素地址开始访问 所以

答案是6

printf("%d\n", strlen(&arr+1));

取出整个数组的地址,+1跳过整个数组,相当与也跳过了数组结尾的'\0' 所以

答案是 随机数

printf("%d\n", strlen(&arr[0]+1));

取出首元素的地址,+1指向数组第二个元素 所以

答案是5
char *p = "abcdef";
printf("%d\n", sizeof(p));

char*类型的p能存放的了这个字符串吗?
当然不行(具体在指针进阶文章里有讲)
这里存放的首元素a的地址 所以

答案是4/8

printf("%d\n", sizeof(p+1));

p是首元素的地址,首元素地址+1指向下一个元素的地址,但还是地址~ 所以

答案是4/8

printf("%d\n", sizeof(*p));

首元素地址解引用找到字符'a' 所以

答案是1

printf("%d\n", sizeof(p[0]));

p[0] == *(p + 0);表示第一个元素 所以

答案是1

printf("%d\n", sizeof(&p));

p表示首元素地址,&p表示取出首元素地址的地址,相当于一个二级指针,但还是地址~ 所以

答案是4/8

printf("%d\n", sizeof(&p+1));

取出首元素地址的地址,+1跳过p这块空间的地址(此处一会画图解释),但还是地址~ 所以

答案是4/8

printf("%d\n", sizeof(&p[0]+1));
取出首元素的地址,+1跳过第一个元素的地址,指向第二个元素地址,但还是地址~ 所以
答案是4/8

---------------------------以下是strlen-----------------------------------

printf("%d\n", strlen(p));

p是首元素地址,strlen计算字符串长度到'\0'停止 所以

答案是6

printf("%d\n", strlen(p+1));

首元素地址+1,指向下一个元素的地址 所以

答案是5

printf("%d\n", strlen(*p));

首元素地址解引用,得到的是首元素,是一个字符'a',和之前的一道题一样,非法访问内存空间 所以

答案是error

printf("%d\n", strlen(p[0]));

和上一题同理 所以

答案是error

printf("%d\n", strlen(&p));

p表示首元素地址,&p表示取出首元素地址的地址,但后面内容是随机初始化(一会画图解释) 所以

答案是 随机值

printf("%d\n", strlen(&p+1));

和上一道题同理,&p+1只是跳过了这个p的地址,后面内容随机初始化 所以

答案是 随机数

printf("%d\n", strlen(&p[0]+1));
取出首元素的地址,+1指向第二个元素的地址,所以

答案是5

对于

printf("%d\n", sizeof(&p+1));

printf("%d\n", strlen(&p+1))

p这个指针变量与"abcdef"的存储位置是不一样的

p是一个局部变量,在栈区上开辟空间,而常量字符串"abcdef"是在静态区开辟的空间

如图:

 +1跳过的是什么呢

如图

 想必这时大家心里因该很清楚啦。


二维数组

        你能做出几道?证明一下自己的实力?

int a[3][4] = {0};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a[0][0]));
printf("%d\n",sizeof(a[0]));
printf("%d\n",sizeof(a[0]+1));
printf("%d\n",sizeof(*(a[0]+1)));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(*(a+1)));
printf("%d\n",sizeof(&a[0]+1));
printf("%d\n",sizeof(*(&a[0]+1)));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));

解析

int a[3][4] = {0};
printf("%d\n",sizeof(a));

数组名单独放在sizeof内部,表示计算整个数组大小,也就是12个整形大小 所以

答案是48

printf("%d\n",sizeof(a[0][0]));

a[0][0] == *(*(a + 0) + 0); 就是第一行第一个元素 所以

答案是4

printf("%d\n",sizeof(a[0]));

a[0] == *(a + 0);这里a表示数组第一行的地址,+0还是第一行,解引用相当于拿到
第一行的数组名,将第一行的数组名单独放入sizeof内部,相当于计算第一行的大小,
(这里这一类比一维数组) 所以

答案是4

printf("%d\n",sizeof(a[0]+1));

与上一道题同理,a[0]拿到第一行的数组名,数组名没有单独放在sizeof内部表示
第一行的首元素地址,第一行首元素的地址+1,指向第一行第二个元素的地址,但还是地址 所以

答案是4/8

printf("%d\n",sizeof(*(a[0]+1)));

与上一道题同理a[0]+1表示第一行第二个元素的地址,解引用相当于找到了第一行第二个元素,是个整形

答案是4

printf("%d\n",sizeof(a+1));

a表示首元素地址,+1跳过第一行的地址,指向第二行的地址,但还是地址~

答案是4/8

printf("%d\n",sizeof(*(a+1)));

与上一题同理,a+1表示第二行地址,第二行的地址解引用相当于找到了第二行的数组名,第二行
数组名单独放入sizeof内部表示计算第二行的数组大小 所以

答案是16

printf("%d\n",sizeof(&a[0]+1));

a[0]表示一行的数组名,&a[0]表示取出第一行数组名的地址,+1指向第二行的数组名的地址 所以

答案是4/8

printf("%d\n",sizeof(*(&a[0]+1)));

与上一题同理,&a[0]+1表示第二行的地址,解引用相当于找到了第二行的数组名,数组名单独放入sizeof
内部,表示计算第二行的大小

答案是16

printf("%d\n",sizeof(*a));

a没有单独放入sizeof内部表示第一行的地址,第一行的地址解引用拿到第一行的数组名,第一行的
数组名单独放入sizeof计算数组第一行的大小 所以

答案是16

printf("%d\n",sizeof(a[3]));

这道题很有意思
可能有的就要说了,这一看就是错的呀,越界访问了~
但其实你可能忘了一点
sizeof只关心的是类型,而非内容
你是否有见过这种写法sizeof(int)
起始就是在计算int的大小,包括平时写int a = 5; sizeof(a);
这也是在计算a这个类型的大小
这道题a[3]就是拿到第四行的数组名,数组名单独放入sizeof内部表示计算数组第四行的大小 所以

答案是16

       


不断揭示数组名的意义本质

1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。

2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。

3. 除此之外所有的数组名都表示首元素的地址。

码字不易~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

陈亦康

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

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

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

打赏作者

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

抵扣说明:

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

余额充值