c语言指针和数组笔试题解析

如果是大佬可以直接跳过解析,直接看结果即可.

目录

前言

一,代码一

解析

结果

 二.代码二

解析

结果

三.代码三

 解析

结果

 四.代码四

解析

结果

五.代码五

解析

结果

总结


前言

本篇文章主要讲解指针和数组在笔试中所遇到的问题及细节

数组名的意义:

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

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

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

指针:指针存放的是地址,标识一块地址空间,指针让内存访问更方便。

指针(地址)的大小在32位是4字节 ,在64位下是8字节.


一,代码一

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//一维数组
int main() {
	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));
	return 0;
}

解析

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

由于是sizeof(数组名),所以sizeof(a)中的数组名a代表着整个数组,计算出来是整个数组的大小,a数组有4个元素,每个元素的数据类型为int,所以结果为16.

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

sizeof(a+0),既不是sizeof(数组名),也不是&数组名,所以这里的a代表着数组首元素的地址,a+0也是代表着首元素的地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节.所以答案是4或者8.

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

这里的a代表的是首元素地址,解引用得到的是首元素1,所的大小为4,结果为4.

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

这里的a代表的是首元素地址,a+1代表第二个元素地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

a[1]为该数组第二个元素为2,数据类型为int,大小为4个字节,答案为4.

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

&a的地址为整个数组的地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

&a的地址为整个数组的地址,解引用为整个数组,即等于sizeof(a),所以结果为16.

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

&a的地址为整个数组的地址,&a+1则跳过是整个数组,但结果还是地址指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.这里配图进行理解.

 

 

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

a[0]为第一个元素,&a[0]为第一个元素的地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

&a[0]为第一个元素的地址,&a[0]+1为第二个元素的地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

结果

左边结果在32为下的结果,右边结果在64为下的结果

 二.代码二

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
//字符数组
int main() {
	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));
	return 0;
}

解析

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

sizeof(数组名)计算的是整个数组的大小,sizeof(arr),arr数组有六个元素每个元素的数据类型为char,所以结果为6.

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

arr这里代表的是首元素的地址,arr+0还是首元素的地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

arr这里代表首元素地址,解引用为数组第一个元素a,数据类型为char,大小为1,所以结果为1.

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

arr[1]为数组第一个元素a,数据类型为char,大小为1,所以结果为1.

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

&arr为整个数组的地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

&arr为整个数组的地址,&arr+1跳过整个数组,但结果还是地址指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.这里配图进行理解.

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

&arr[0]为第一个元素的地址,&arr[0]+1为第二个元素的地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

arr这里代表的是整个数组的地址,这里就要了解strlen函数的性质,strlen() 函数从字符串的开头位置依次向后计数,直到遇见\0,然后返回计时器的值。最终统计的字符串长度不包括\0。

由于arr数组里没有\0元素,所以还会一直找下去,不知道在哪里会遇到\0,所以给出的答案是一个随机值.

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

arr为第一个元素的地址,arr+0为第一个元素的地址,跟上一个代码运行情况相同,所以在这里不在继续解释,答案是随机值,且与上一个代码运行结果相同.

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

arr代表第一个元素的地址,解引用为第一个元素a,由于strlen()函数的参数是地址,就会将a的ASCII的值97当做一个地址进行访问,运行时就会出现错误,错误原因为:引发的异常: 0xC0000005: 读取位置 0x00000061 时发生访问冲突。所以该运行结果为error.

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

arr[1]为数组的第二个元素b,与上一个代码同理,在这里不在进行解释,错误原因为:引发的异常: 0xC0000005: 读取位置 0x00000062 时发生访问冲突。所以该运行结果为error.

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

&arr为整个数组的地址,跟strlen(arr)相同,由于arr数组里没有\0元素,所以还会一直找下去,不知道在哪里会遇到\0,所以给出的答案是一个随机值.

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

&arr为整个数组的地址,&arr+1跳过整个数组,在这里我们还配图解释.

 由于跳过整个数组,该数组有六个元素,所以答案应为,上一个代码的随机值-6

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

&arr[0]为第一个元素的地址,&arr[0]+1为第二个元素的地址,所以根据上个代码理解,该代码的答案为随机值-1.

结果

左边结果在32为下的结果,右边结果在64为下的结果,由于有错误代码我中间省略用error代替.

感兴趣的小伙伴可以试一下错误代码会提示什么问题,以便更深入了解.

三.代码三

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
//字符数组
int main() {
	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));
	return 0;
}

 解析

注意:这里数组arr是用字符串初始化的数组,所以该数组的元素有7个,第七个元素为"\0"

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

sizeof(arr)为整个数组的大小,该数组有7个元素,每个元素的数据类型为char,所以答案为7.

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

arr为首元素的地址arr+0也是首元素的地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

arr为第一个元素的的地址,解引用为第一个元素a,数据类型为char,所以答案为1.

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

arr[1]为数组的第二个元素b,数据类型为char,所以答案为1.

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

&arr为整个元素的地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

&arr为整个数组的地址,&arr+1跳过整个数组,这里为了更方便理解我们配图解释.

 指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

&arr[0]+1为数组第二个元素的地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

arr为整个数组的地址,strlen() 函数从字符串的开头位置依次向后计数,直到遇见\0,然后返回计时器的值。最终统计的字符串长度不包括\0。所以答案为6.

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

arr+0为第一个元素的地址,所以答案为6.

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

arr代表第一个元素的地址,解引用为第一个元素a,由于strlen()函数的参数是地址,就会将a的ASCII的值97当做一个地址进行访问,运行时就会出现错误,错误原因为:引发的异常: 0xC0000005: 读取位置 0x00000061 时发生访问冲突。所以该运行结果为error.

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

arr[1]为数组的第二个元素b,与上一个代码同理,在这里不在进行解释,错误原因为:引发的异常: 0xC0000005: 读取位置 0x00000062 时发生访问冲突。所以该运行结果为error.

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

&arr为整个数组的地址,所以答案为6.注意:这里是strlen,不要跟sizeof搞混了.

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

还是这张图.

 

所以还会一直找下去,不知道在哪里会遇到\0,所以给出的答案是一个随机值.

注:随机值不要与其他值进行比较

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

&arr[0]为第一个元素的地址,&arr[0]+1为第二个元素的地址,所以答案为5.

结果

左边结果在32为下的结果,右边结果在64为下的结果,由于有错误代码我中间省略用error代替.

 四.代码四

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
//字符数组
int main() {
	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));
}

解析

这里便于更直观,请看图!

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

p是个指针(存的是数组首元素的地址),指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

p为数组首元素地址,p+1为数组第二个元素地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

*p为数组首元素a,所以为1.

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

p[0]为数组的第一个元素,也可以写成*(p+0)这两个是等价的,所以答案为1.

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

&p是p的地址,指针(地址)的大小在32位是4字节 ,在64位下是8字节,所以答案是4或者8.

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

&p+1为p地址后面的地址具体指向哪里不知道,但还是个地址,所以答案是4或者8.

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

&p[0]为首元素地址,&p[0]+1为数组第二个元素的地址,所以答案是4或者8.

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

p为数组首元素地址,所以答案为6.

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

p+1为数组第二个元素的地址,所以答案为5.

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

*p为数组第一个元素a,程序错误,不在进行过多解释,与上面的程序错误相同.

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

p[0]为数组第一个元素a,程序错误,不在进行过多解释,与上面的程序错误相同.

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

&p为p的地址,后面是否在哪里存在\0不知道,所以是随机值.

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

与上一个代码同理,也是随机值.

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

&p[0]+1为数组第二个元素的地址,所以答案为5.

结果

左边结果在32为下的结果,右边结果在64为下的结果,由于有错误代码我中间省略用error代替.

 

五.代码五

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//二维数组
int main() {
	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]));
}

解析

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

sizeof(数组名)计算的是整个数组的大小,所以答案为48.

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

a[0][0]为数组第一个元素,数据类型为int,所以答案为4.

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

a[0]表示数组的第一行元素,由于是二维数组所以答案为16.

如果不理解的话可以认为a[0]为第一行元素的数组名.

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

a[0]+1为数组的第一行第二个元素的地址,所以答案为4或8.

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

*(a[0]+1)为数组的第一行第二个元素,数据类型为int,所以答案为4.

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

a为二维数组的第一行的地址,a+1为数组第二行的地址,所以答案为4或8.

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

*(a+1)为第二行元素,所以答案为16.

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

&a[0]+1为数组第二行元素的地址,所以答案为4或8.

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

*(&a[0] + 1))为数组第二行元素,所以答案为16.

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

*a为数组第一行地址,所以答案为16.

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

a[3]这里有小伙伴就会发现数组越界了,非法访问了吗?所以程序应该出现错误,实则不然.这里就要深入了解以下sizeof()函数了.sizeof()内部的表达式是不计算的,不会真的去访问的,所以不会出现非法访问的问题,所以其实不存在也能通过类型计算大小.所以答案为16.

便于理解sizeof()函数我写了一段代码来分析.

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main() {
	short b = 5;
	int a = 4;
	printf("%d\n", sizeof(b = a + 6));
	printf("%d\n", b);
}

这里我们分析以下结果是什么呢?

经过分析我得出的答案是

2

5

sizeof()内部的表达式是不计算的,这样大家能够理解了吗.

结果

那我们运行一下,左边结果在32为下的结果,右边结果在64为下的结果

 呼呼终于完事了,离成功又进了一部,我把我学习c语言的经历分享出来,大家一起进步!

在这里还是感谢那些可以看到底的小伙伴,学到就是赚到,学到才是王道.哈哈哈

鸡你太美!


总结

数组名的意义:

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

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

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

指针:指针存放的是地址,标识一块地址空间,指针让内存访问更方便。

指针(地址)的大小在32位是4字节 ,在64位下是8字节.

二维数组的数组名为第一行的元素记住哦!

小小up制作不易请给点赞吧!球球了.😜

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

笔写落去

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

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

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

打赏作者

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

抵扣说明:

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

余额充值