当前位置:网站首页>【数组和进阶指针经典笔试题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没有变)
边栏推荐
- Assembly language
- webRTC SDP mslabel lable
- Discussion on memset assignment
- Lepton 无损压缩原理及性能分析
- Explain Vue's plan to clean up keepalive cache in time
- 周大福践行「百周年承诺」,真诚服务推动绿色环保
- 注意!软件供应链安全挑战持续升级
- Solution of commercial supply chain collaboration platform in household appliance industry: lean supply chain system management, boosting enterprise intelligent manufacturing upgrading
- Mysql database installation tutorial under Linux
- Thymeleaf common functions
猜你喜欢
随机推荐
leetcode:881. 救生艇
dynamic programming
周大福践行「百周年承诺」,真诚服务推动绿色环保
通过npm 或者 yarn安装依赖时 报错 出现乱码解决方式
Structure - C language
APR protocol and defense
Share 20 strange JS expressions and see how many correct answers you can get
有一个强大又好看的,赛过Typora,阿里开发的语雀编辑器
Faire un clip vidéo auto - média deux fois, comment clip n'est pas considéré comme une infraction
Opengauss database source code analysis series articles -- detailed explanation of dense equivalent query technology (Part 2)
03_ Dataimport of Solr
做自媒體視頻二次剪輯,怎樣剪輯不算侵權
Fonctions communes de thymeleaf
ASP. Net large takeout ordering system source code (PC version + mobile version + merchant version)
Sharing the 12 most commonly used regular expressions can solve most of your problems
Show strength. In this way, the mobile phone will not be difficult to move forward
Thymeleaf th:with use of local variables
CPU设计实战-第四章实践任务二用阻塞技术解决相关引发的冲突
家用电器行业商业供应链协同平台解决方案:供应链系统管理精益化,助推企业智造升级
Total amount analysis accounting method and potential method - allocation analysis