进阶C语言:指针笔试题

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 关于C指针的经典笔试题,做完这些你也可以轻松拿捏指针。

在学习完进阶C指针之后,可以来做一些笔试题来进行提升、巩固,小编在这里给大家分享几道比较有意思的笔试题

紫蓝色几何渐变科技互联网微信公众号封面 (1).gif

目录

 

一、笔试题1:

二、笔试题2

三、笔试题3:

四、笔试题4:

五、笔试题5:

六、笔试题6:

七、笔试题7:

八、笔试题8:


一、笔试题1:

//代码的运行结果是什么?#include <stdio.h>intmain()
{
inta[5] = { 1, 2, 3, 4, 5 };
int*ptr= (int*)(&a+1);
printf("%d,%d", *(a+1), *(ptr-1));
return0;
}

image.gif

解析:

这是一段比较简单的代码,关于上面的代码,可以分析一下,a是一个整形数组,里面有五个元素,ptr是一个整形指针,&a+1表示的是跳过一个a数组,类型是一个数组指针的类型,所以要强制转换为整形指针才可以存放在ptr中,所以ptr指向的就是a数组后面的那个地址。

image.gif编辑

*(a+1)中的a表示数组首元素的地址,+1表示跳过一个整形,指向数组的第二个元素的地址,然后解引用,得到数组的第二个元素,所以*(a+1)的结果是2

*(ptr-1)中的ptr是一个整形指针,指向的是a数组后面的地址,-1表示向前移动1个整形,所以指向了数组的最后一个元素的地址,然后解引用,得到的就是数组的最后一个元素,所以*(ptr-1)的结果是5

二、笔试题2

假设p 的值为0x100000。 如下表表达式的值分别为多少?

已知,结构体Test类型的变量大小是20个字节

#include <stdio.h>structTest{
intNum;
char*pcName;
shortsDate;
charcha[2];
shortsBa[4];
}*p;
intmain()
{
printf("%p\n", p+0x1);
printf("%p\n", (unsignedlong)p+0x1);
printf("%p\n", (unsignedint*)p+0x1);
return0;
}

image.gif

解析:

Test是一个结构体,p是一个结构体指针,已知结构体的大小是20,所以结构体指针在加减整数的时候移动的单位就是20,p的初始值为0x100000,这是一个16进制的数字,以0x开头的为16进制数字

p+0x1中的p指向的是结构体,+1表示跳过一个结构体,由已知结构体的大小是20,所以p由起始的0x100000要加上20,20的16进制就是0x14,所以p+0x1的结果是0x100014

(unsigned long)p+0x1表示先把p强制类型转化为无符号长整形然后再加1,既然是整形那就相当于整数,整数加1就只是单纯的加1,所以(unsigned long)p+0x1的结果是0x100001

 (unsigned int*)    p + 0x1表示先把p强制类型转化为无符号的整形指针,既然是整形指针,加减整数表示跳过整形个单位,所以(unsigned int*)p + 0x1的结果是0x100004

三、笔试题3:

//代码运行结果是什么?#include <stdio.h>intmain()
{
inta[4] = { 1, 2, 3, 4 };
int*ptr1= (int*)(&a+1);
int*ptr2= (int*)((int)a+1);
printf("%x,%x", ptr1[-1], *ptr2);
return0;
}

image.gif

解析:

a是一个整形数组,&a+1表示取出整个数组的地址然后地址跳过一个数组,这时它的类型是一个指针数组的类型,强制类型转化为int*用ptr1来接受,ptr[-1]可以写成*(ptr-1),ptr是一个整形指针,-1表示移动一个整形,所以就指向了4这个元素的地址,然后解引用就得到了4

所以ptr[-1]的结果是4

a表示数组首元素的地址,然后将其强制类型转化为int类型,然后+1就表示单纯的加1,如果这时a的地址是0x0012ff40,那么+1之后的结果就变成了0x0012ff41,也就是说地址移动了一个字节,然后再将其强制类型转化为int*用ptr2来接收,如果机器是小端存储模式,那么a数组在内存中存储的方式就是01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00,移动一个字节之后的地址就变成了00 00 00 02 00 00 00 03 00 00 00 04 00 00 00,又因为ptr2是整形指针,解引用向后面访问4个字节,所以就得到了00 00 00 02,这个值在小端的存储模式下表示的值是 02 00 00 00,所以*ptr2的结果是2000000

image.gif编辑

image.gif编辑

四、笔试题4:

//代码运行结果是什么?#include <stdio.h>intmain()
{
inta[3][2] = { (0, 1), (2, 3), (4, 5) };
int*p;
p=a[0];
printf("%d", p[0]);
return0;
}

image.gif

解析:

如果仔细观察这个二维数组,可以发现它其实只有三个元素:1 3 5,而并非0 1 2 3 4 5,为什么呢?可以发现在{}里面用()分隔的元素,其实在()里面是一个逗号表达式,逗号表达式的结果是最后一个表达式的结果,所以(0,1)的结果是1,(2,3)的结果是3,(4,5)的结果是5,所以二维数组里面第一行的元素就是1,3,5,a[0]表示第一行的地址,将其存放在p里面,p[0]表示的就是第一行中下标为0的元素,所以p[0]的结果是1

五、笔试题5:

//代码运行结果#include <stdio.h>intmain()
{
inta[5][5];
int(*p)[4];
p=a;
printf("%p,%d\n", &p[4][2] -&a[4][2], &p[4][2] -&a[4][2]);
return0;
}

image.gif

解析:

指针-指针得到的是两个指针之间的元素个数

%p在打印的时候是直接将内存里面的值进行打印

int(*p)[4]表示的是一个数组指针,p指向的是一个整形指针,里面有四个元素,也就是意味着p+1只能跳过4个字节

image.gif编辑

通过图来看&p[4][2]是低地址,而&a[4][2]是高地址,所以&p[4][2] - &a[4][2] = -4,-4如果使用%d的形式来打印就是-4,但是如果是以%p的形式来打印就得计算了:

-4的原码:10000000000000000000000000000100

-4的反码:1111111111111111111111111111111111011

-4的补码:1111111111111111111111111111111111100

所以在以%p的形式来打印-4时会打印-4的补码,四位的1是一个F,所以-4的补码转化为16进制就是FFFFFFFC,所以&p[4][2] - &a[4][2], &p[4][2] - &a[4][2]的结果分别为FFFFFFFC和-4

六、笔试题6:

#include <stdio.h>intmain()
{
intaa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int*ptr1= (int*)(&aa+1);
int*ptr2= (int*)(*(aa+1));
printf("%d,%d", *(ptr1-1), *(ptr2-1));
return0;
}

image.gif

解析:

&aa拿到aa二维数组的整个地址,+1跳过整个数组,然后强制类型转化为int*的指针赋给ptr1,所以*(ptr1 - 1)的结果是10

aa表示二维数组第一行的地址,+1表示跳过一行,指向了第二行,然后解引用拿到了第二行的元素,再进行强制类型转化为int*的指针赋给ptr2,所以ptr2指向的就是数组第二行的起始地址,所以*(ptr2 - 1)的结果是5

七、笔试题7:

#include <stdio.h>intmain()
{
char*a[] = { "work","at","alibaba" };
char**pa=a;
pa++;
printf("%s\n", *pa);
return0;
}

image.gif

解析:

以前提到过一个常量字符串放进指针里面的时候存放的是它的首字符的地址,所以a这个指针数组里面存放的是w、a、a的地址,然后使用一个二级指针来接收a,在这里的a表示数组首元素的地址,也就是w的地址,pa++跳过一个字符指向了a,然后*pa得到的就是a字符往后的元素,所以*pa的结果是at

八、笔试题8:

//代码的运行结果是什么?#include <stdio.h>intmain()
{
char*c[] = { "ENTER","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);
return0;
}

image.gif

解析:

printf("%s\n", **++cpp);

++cpp是前置++,先++后使用,所以cpp指向了POINT,所以**++cpp的结果是POINT

image.gif编辑

printf("%s\n", *-- * ++cpp + 3);

这时的cpp指向的是c+2的地址,++cpp指向了c+1的地址,然后*++cpp得到了c+1的这块空间,c+1指向的是NEW,然后--,表示c+1的这块空间--,所以c+1指向的就变成了ENTER,然后再解引用拿到的是ENTER这个字符串,再+3表示ENTER跳过三个字节指向了ER,所以*-- * ++cpp + 3的结果是ER

image.gif编辑

printf("%s\n", *cpp[-2] + 3);

这时的cpp指向的是c+1的地址,*(cpp - 2) = cpp[-2],所以cpp指向的是c+3的地址,然后解引用拿到了这块空间,这块空间里面存放的是FIRST,然后+3FIRST跳过三个字节,所以*cpp[-2] + 3的结果是ST

image.gif编辑

printf("%s\n", cpp[-1][-1] + 1);

cpp[-1][-1]可以拆解为*(*(cpp-1)-1),这时的cpp指向的是c+3的地址,-1然后解引用得到的是c+2的这块空间,这块空间指向的是POINT,然后再-1解引用就得到了NEW,再+1跳过一个字节,所以cpp[-1][-1] + 1的结果是EW

image.gif编辑

程序运行结果为:

POINT
ER
ST
EW

本期分享到此结束,喜欢的老铁留下关注再走吧,万分感谢!

目录
相关文章
|
16天前
|
存储 人工智能 Java
一文轻松拿捏C语言的指针的基础使用
本文介绍了C语言中的指针概念,包括直接访问和间接访问内存的方式、指针变量的定义与使用、取址运算符`&`和取值运算符`*`的应用,帮助读者深入理解指针这一C语言的核心概念。君志所向,一往无前!
20 0
|
3月前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
135 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
3月前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
340 9
|
3月前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
77 7
|
4月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
4月前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
273 3
|
4月前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
86 1
|
4月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
344 13
|
5月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
65 0
|
6月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
221 4