当前位置:网站首页>【数组和进阶指针经典笔试题12道】这些题,满足你对数组和指针的所有幻想,come on !
【数组和进阶指针经典笔试题12道】这些题,满足你对数组和指针的所有幻想,come on !
2022-07-05 14:34:00 【每天都要坚持刷题】
众所周知,指针是C语言的灵魂,很多人就是倒在指针的脚下。今天,我来带大家看一看指针在笔试中是怎么考的吧!(提示:本篇博客测试环境是vs-x64,该环境下指针占8个字节)
练习题1
int main()
{
int a[4] = { 1,2,3,4 };
printf("%u\n", sizeof(a));//16-sizeof(数组名)-整个数组
printf("%u\n", sizeof(a+0));//8-不是单独的数组名-数组首元素的地址
printf("%u\n", sizeof(*a));//4-数组首元素的地址解引用-数组首元素
printf("%u\n", sizeof(a+1));//8-数组第2个元素的地址
printf("%u\n", sizeof(a[1]));//4-数组第2个元素
printf("%u\n", sizeof(&a));//8-整个数组的地址
printf("%u\n", sizeof(*&a));//16-对整个数组的地址解引用,得到的是整个数组-sizeof(数组名)
printf("%u\n", sizeof(&a+1));//8-&a是整个数组的地址,+1跳过一个数组,还是一个数组的地址
printf("%u\n", sizeof(&a[0]));//8-首元素的地址
printf("%u\n", sizeof(&a[0]+1));//8-第2个元素的地址
return 0;
}
练习题2
int main()
{
char str[5] = { 'a','b','c','d','e' };
printf("%d\n", sizeof(str));//5-sizeof(数组名)-整个数组
printf("%d\n", sizeof(str+0));//8-数组首元素的地址
printf("%d\n", sizeof(*str));//1-数组首元素
printf("%d\n", sizeof(str[1]));//1-数组第二个元素
printf("%d\n", sizeof(&str));//8
printf("%d\n", sizeof(&str[0]+1));//8
printf("%d\n", sizeof(str[0]+1));//4-字符和整型相加-整型提升
//等价于printf("%d\n", sizeof('a'+1));//4-整型提升
return 0;
}
练习题3
int main()
{
char str[] = { 'a','b','c','d','e' };
printf("%d\n", strlen(str));//随机值
printf("%d\n", strlen(str+0));//随机值
printf("%d\n", strlen(*str));//strlen('a')-->strlen(97);//野指针
printf("%d\n", strlen(str[1]));//野指针
printf("%d\n", strlen(&str));//随机值
printf("%d\n", strlen(&str+1));//随机值
printf("%d\n", strlen(&str[0]+1));//随机值
return 0;
}
这里的第三个printf处如果调试的话,这个错误代表的意思就是访问了非法内存(有一些内存地址是没有办法访问的,有一些是允许访问,但是也会进行一定的检测)
关于sizeof和strlen:
strlen是求字符串长度的,关注的是字符串中的'\0',计算的是\0之前出现字符的个数
strlen是库函数,只针对字符串
sizeof只关注占用内存的大小,不在乎内存中放的是什么
sizeof是操作符
练习题4
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//3*4*4=48-整个二维数组
printf("%d\n", sizeof(a[0]));//8错//4*4=16对 sizeof(一维数组数组名)-整个第一个一维数组
printf("%d\n", sizeof(a[0]+1));//8-第2个一维数组的地址
printf("%d\n", sizeof(a[0][0]));//4-第一个一维数组的第1个元素
printf("%d\n", sizeof(*(a[0]+1)));//4-第一个一维数组的第2个元素
printf("%d\n", sizeof(*(a+1)));//8错//4*4=16对 sizeof(一维数组数组名)-整个第2个一维数组
printf("%d\n", sizeof(a+1));//8-第2个一维数组的地址
printf("%d\n", sizeof(&a[0]+1));//8-第一个一维数组的第2个元素
printf("%d\n", sizeof(*a));//4*4=16-整个第一个一维数组
printf("%d\n", sizeof(a[3]));//16-整个第四个一维数组
return 0;
}
练习题5
int main()
{
int a[5] = { 1,2,3,4,5 };
int* ptr = (int*)(&a + 1);
printf("%d %d", *(a + 1), *(ptr - 1));//2 5
return 0;
}
练习题6
struct Test
{
int num1;
char* num2;
short num3;
char num4[2];
short num5[4];
}*p;
//假设p的值为0x100000,如下表达式的值分别是多少?
//已知在当前环境下,Test类型的变量大小是20个字节
//考察:指针/整数+1到底是加了多少
int main()
{
printf("%p\n", p + 0x1);//0x100014
printf("%p\n", (unsigned long)p + 0x1);//0x100001
printf("%p\n", (unsigned int*)p + 0x1);//0x100004
return 0;
}
0x1就是十六进制的1,也就是十进制的1:
对于第一个p+0x1中p是struct Test* 类型的指针,加1,跳过一个sizeof(struct Test)==20,也就是0x00014大小。
同理第二个p是被强制转换为了unsigned long类型,是一个整数,整数=1就是+1,然后按照%p打印出来,加的因为就是1(没有超过16),所以和在原来的0x10000上加1是一样的。
同理第三个p是被强制转换为了unsigned int*类型,加1,加的是4个字节。
练习题7
int main()
{
int a[4] = { 1,2,3,4 };
int* ptr1 = (int*)(&a + 1);
int* ptr2 = (int*)(a + 1);
int* ptr3 = (int*)((int)a + 1);
int* ptr4 = (int*)((char*)a + 1);
printf("%x %x %x %x\n\n", ptr1[-1], *ptr2,*ptr3,*ptr4);//
return 0;
}
ptr3得到的方式是:
通过将整型指针强制转换为整型数值,然后加1,最后再强制转换为整型指针;
ptr4得到的方式是:
通过将整型指针强制转换为字符指针,然后加1,最后再强制转换为整型指针。
两个的效果是一样的。
练习题8
int main()
{
int a[3][2] = { (0,1),(2,3),(3,4) };//坑点:逗号表达式
int* p;
p = a[0];
printf("%d\n", p[0]);
//等价于printf("%d\n", *p);
return 0;
}
练习题9
int main()
{
int a[4][5];
int(*p)[3];//重点在于这里的3,不是5
p = a;
printf("%p %d\n", &p[3][2] - &a[3][2], &p[3][2] - &a[3][2]);
return 0;
}
关于-6变FFFFFA:
练习10
int main()
{
int a[2][5] = { 1,2,3,4,5,6,7,8,9,10 };
int* ptr1 = (int*)(&a + 1);
int* ptr2 = (*(a + 1));
//等价于int* ptr2 = (int*)(a + 1);
printf("%d %d\n", *(ptr1 - 1), *(ptr2 - 1));//10 5
return 0;
}
练习11
int main()
{
char* a[] = { "I will work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
练习题12
int main()
{
char* c[] = { "ENTRE","NEW","POINT","FIRST" };
char** cp[] = { c + 3,c + 2,c + 1,c };
char*** cpp = 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;
}
下面是我自己的理解方式:
[]和*都可以过桥(也就是找到指针所指向的那个目标), cpp[-1]就是指向的*(cpp-1),就是先指针-1(指向发生改变),然后过桥(找到指针指向的那个目标);
然后这里的虚线就是不会有自增++有副作用
a=a+1;有副作用(a变了)
但是a+1;就没有副作用(a没有变)
边栏推荐
猜你喜欢
CPU设计相关笔记
How to deeply understand the design idea of "finite state machine"?
Thymeleaf th:classappend attribute append th:styleappend style append th:data- custom attribute
PyTorch二分类时BCELoss,CrossEntropyLoss,Sigmoid等的选择和使用
FR练习题目---综合题
Thymeleaf 模板的创建与使用
网上电子元器件采购商城:打破采购环节信息不对称难题,赋能企业高效协同管理
日化用品行业智能供应链协同系统解决方案:数智化SCM供应链,为企业转型“加速度”
用 Go 跑的更快:使用 Golang 为机器学习服务
FR练习题目---简单题
随机推荐
Loop invariant
After the microservice project is deployed, static resources and files uploaded to upload cannot be accessed. Solution
浅谈Dataset和Dataloader在加载数据时如何调用到__getitem__()函数
Opengauss database source code analysis series articles -- detailed explanation of dense equivalent query technology (Part 2)
PyTorch二分类时BCELoss,CrossEntropyLoss,Sigmoid等的选择和使用
循环不变式
申请代码签名证书时如何选择合适的证书品牌?
家用电器行业商业供应链协同平台解决方案:供应链系统管理精益化,助推企业智造升级
APR protocol and defense
在Pytorch中使用Tensorboard可视化训练过程
Thymeleaf common functions
【NVMe2.0b 14-9】NVMe SR-IOV
Intelligent supply chain collaboration system solution for daily chemical products industry: digital intelligent SCM supply chain, which is the "acceleration" of enterprise transformation
Sharing the 12 most commonly used regular expressions can solve most of your problems
Discussion on memset assignment
729. 我的日程安排表 I :「模拟」&「线段树(动态开点)」&「分块 + 位运算(分桶)」
LeetCode_ 2 (add two numbers)
Introduction, installation, introduction and detailed introduction to postman!
Explain Vue's plan to clean up keepalive cache in time
TS所有dom元素的类型声明