C语言——指针面试题详解

news2025/2/28 6:43:03
🐒个人主页:平凡的小苏
📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情

目录

 1. 指针和数组笔试题解析

 一维数组

字符数组

二维数组

2. 指针笔试题

笔试题1:

笔试题2:

笔试题3

 笔试题4

 笔试题5

笔试题6  

笔试题7

笔试题8


 1. 指针和数组笔试题解析

数组名的意义:

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

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

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

 一维数组

int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
//这里数组名单独放在sizeof内部,计算整个数组的大小,结果为16
printf("%d\n",sizeof(a+0));
//这里数组名没有单独放在sizeof内部,是数组首元素的地址,结果为4/8
printf("%d\n",sizeof(*a));
//这里数组首元素的地址解引用,计算的是元素大小,结果为4
printf("%d\n",sizeof(a+1));
//这里数组首元素地址加1,也是地址,是地址结果就是4/8
printf("%d\n",sizeof(a[1]));
//这里计算元素大小,结果为4
printf("%d\n",sizeof(&a));
//取出整个数组的地址,是地址结果就为4/8
printf("%d\n",sizeof(*&a));
//取出数组的地址,然后解引用,本质是数组名单独放在sizeof内部,结果为16
printf("%d\n",sizeof(&a+1));
//地址加1,是地址结果就为4/8
printf("%d\n",sizeof(&a[0]));
//取出首元素的地址,是地址结果就为4/8
printf("%d\n",sizeof(&a[0]+1));
//结果为4/8

字符数组

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));
//数组名单独,结果为6,因为sizeof计算的是占用内存的大小,不用找\0,并且看类型
printf("%d\n", sizeof(arr+0));
//数组首元素的地址,是地址结果就为4/8
printf("%d\n", sizeof(*arr));
//数组首元素地址解引用,计算元素大小,结果为1
printf("%d\n", sizeof(arr[1]));
//结果为1
printf("%d\n", sizeof(&arr));
//取地址,是地址结果就为4/8
printf("%d\n", sizeof(&arr+1));
//是地址结果为4/8
printf("%d\n", sizeof(&arr[0]+1));
//取出首元素地址加1,跳过四个字节,是地址结果为4/8



printf("%d\n", strlen(arr));
//strlen是遇到'\0'停止,这个不知道什么时候遇到'\0',所以结果为随机值
printf("%d\n", strlen(arr+0));
//同上为随机值
printf("%d\n", strlen(*arr));
//对arr解引用拿到第一个字符,转为十进制为97,strlen是用地址一个一个访问的,所以这个代码error
printf("%d\n", strlen(arr[1]));
//同上error
printf("%d\n", strlen(&arr));
//随机值
printf("%d\n", strlen(&arr+1));
//随机值
printf("%d\n", strlen(&arr[0]+1));
//随机值
char arr[] = "abcdef";
//“abcdef\0”数组长度为7
printf("%d\n", sizeof(arr));
//计算整个数组大小,结果为7
printf("%d\n", sizeof(arr+0));
数组首元素的地址,是地址就为4/8
printf("%d\n", sizeof(*arr));
//计算数组元素的大小,结果为1
printf("%d\n", sizeof(arr[1]));
//同上,结果为1
printf("%d\n", sizeof(&arr));
//取出整个数组的地址,是地址,结果就为4/8
printf("%d\n", sizeof(&arr+1));
//取出数组的地址加1,跳过数组,指向数组后边,但也是地址,是地址结果就为4/8
printf("%d\n", sizeof(&arr[0]+1));
//是地址结果就为4/8


printf("%d\n", strlen(arr));
//strlen遇到斜杠0就停止,结果为6
printf("%d\n", strlen(arr+0));
//同上,结果为6
printf("%d\n", strlen(*arr));
//解引用拿到的是字符a,代码错误
printf("%d\n", strlen(arr[1]));
//同上,代码错误
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));
//该指针变量存放的是该字符串首字符的地址,是地址结果就为4/8
printf("%d\n", sizeof(p+1));
//是地址结果就为4/8
printf("%d\n", sizeof(*p));
//对指针p解引用,计算的是该字符元素的大小,结果为1
printf("%d\n", sizeof(p[0]));
//同上,结果为1
printf("%d\n", sizeof(&p));
//是地址,结果就为4/8
printf("%d\n", sizeof(&p+1));
//是地址,结果就为4/8
printf("%d\n", sizeof(&p[0]+1));
同上,结果为4/8;

printf("%d\n", strlen(p));
//strlen遇到'\0'就停止,结果为6
printf("%d\n", strlen(p+1));
//p+1跳过一个字节,结果为5
printf("%d\n", strlen(*p));
//拿到的是字符a,转为ascii吗为97,该代码错误
printf("%d\n", strlen(p[0]));
//同上,该代码错误
printf("%d\n", strlen(&p));
//取p的地址,不知道什么时候遇到斜杠0,所以为随机值
printf("%d\n", strlen(&p+1));
同上,结果为随机值
printf("%d\n", strlen(&p[0]+1));
取首字符的地址+1跳过一个字节,计算的结果为5

二维数组

int a[3][4] = {0};
printf("%d\n",sizeof(a));
//结果为48,3*4*4=48
printf("%d\n",sizeof(a[0][0]));
//计算元素的大小结果为4
printf("%d\n",sizeof(a[0]));
//a[0]是第一行一维数组的数组名,数组名单独放在sizeof内部,计算的是第一行数组的大小,结果为16
printf("%d\n",sizeof(a[0]+1));
//没有单独放在sizeof内部,是数组的首元素,+1跳过四个字节,指向第一行第二列的地址,是地址就为4/8
printf("%d\n",sizeof(*(a[0]+1)));
//计算的是元素的大小结果为4
printf("%d\n",sizeof(a+1));
//a没有单独放在sizeof内部,是首元素的地址,是第一行的地址,+1指向第二行的地址,是地址就为4/8
printf("%d\n",sizeof(*(a+1)));
a没有单独放在sizeof内部,是首元素的地址,是第一行的地址,+1指向第二行的地址,进行解引用得到第二行的数组名,计算的是第二行数组的大小结果为16
printf("%d\n",sizeof(&a[0]+1));
取出第一行的地址,再+1指向第二行的地址,是地址就为4/8
printf("%d\n",sizeof(*(&a[0]+1)));
取出第一行的地址,再+1指向第二行的地址,再进行解引用,得到第二行的数组名,计算的是第二行数组的大小,结果为16
printf("%d\n",sizeof(*a));
a是二维数组的数组名,没有单独放sizeof内部,是一维数组第一行的地址,然后进行解引用,得到第一行的数组名,计算的是第一行数组的大小,结果为16
printf("%d\n",sizeof(a[3]));
//第四行的数组名,虽然越界了但是知道了列,就知道一行有多少个元素,因为sizeof是看类型计算的大小,sizeof再编译阶段就完成了计算,越界不影响,所以结果为16

2. 指针笔试题

笔试题1

int main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    int *ptr = (int *)(&a + 1);
    printf( "%d,%d", *(a + 1), *(ptr - 1));
    return 0;
}
//程序的结果是什么?
2 5
解释:1.a是数组名,为数组首元素的地址,加1跳过4个字节,在进行解引用就得到了2
2.取出数组的地址再进行+1,跳过整个数组,因为取出数组的地址是数组指针类型,想要放在ptr里面,就需要强制类型转换。ptr-1往回跳一个字节再进行解引用得到的结果为5.

笔试题2:

//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
 int Num;
 char *pcName;
 short sDate;
 char cha[2];
 short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
 printf("%p\n", p + 0x1);
 printf("%p\n", (unsigned long)p + 0x1);
 printf("%p\n", (unsigned int*)p + 0x1);
 return 0;
}
结果为:00100014,00100001,00100004
解释:1.因为结构体的大小为20个字节,指针p+1跳过20个字节所以结果为00100014
2.先将p强制类型转换为无符号整型,整型+1就跳过一个字节,所以地址为00100001
3.将p强制类型转换为无符号整型指针,无符号整型指针+1就跳过四个字节,所以地址为00100004

笔试题3

int main()
{
    int a[4] = { 1, 2, 3, 4 };
    int *ptr1 = (int *)(&a + 1);
    int *ptr2 = (int *)((int)a + 1);
    printf( "%x,%x", ptr1[-1], *ptr2);
    return 0;
}
结果为:4,2000000

解释如图所示:

 笔试题4
 

#include <stdio.h>
int main()
{
    int a[3][2] = { (0, 1), (2, 3), (4, 5) };
    int *p;
    p = a[0];
    printf( "%d", p[0]);
 return 0;
}
结果为:1
解释:因为该数组里面的括号为逗号表达式,所以数组的元素为1 3 5 0 0 0
p[0]访问的是a[0][0]所以打印出来的是1

 笔试题5

int main()
{
    int a[5][5];
    int(*p)[4];
    p = a;
    printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    return 0;
}
int main()
{
    int aa[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));
    return 0;
}

 

 解释:&p[4][2]-&a[4][2]两个指针相减得到的是-4,又因为-4放入内存是补码

则-4的补码为:11111111111111111111111111111100,所以它的地址为fffffc。用%p打印出来就是fffffc

而用%d打印就是-4.

笔试题6  

int main()
{
    int aa[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));
    return 0;
}
结果为:10 5
解释:1.取出二维数组的地址+1,跳过整个二维数组,强制类型转换为int*,放入ptr1,然后ptr-1再进行解引用得到的就是10
2.aa是数组名,是一维数组的数组名,是第一行数组的地址,aa+1跳过一行得到第二行的地址解引用,强制类型转换为int*放入ptr2,ptr2-1再进行解引用打印出来的就是5

笔试题7

#include <stdio.h>
int main()
{
 char *a[] = {"work","at","alibaba"};
 char**pa = a;
 pa++;
 printf("%s\n", *pa);
 return 0;
}
结果为:at
解释:a数组每个元素的类型为char*,所以需要二级指针来接收数组a的地址,然后pa++,跳过一个字节,所以pa指向了a首字符的地址,再对pa进行解引用找到了字符a利用%s打印出来就是at

笔试题8

int main()
{
 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);
 return 0;
}
结果为:POINT  ,ER, ST, EW

解释:cpp存放的是cp首元素的地址,cp 存放的是c的地址

1.由操作符优先级可知,先进行++cpp,所以cpp指向了c+2,然后对cpp第一次解引用得到了c+2的地址,再进行解引用找到了POINT首字符的地址,所以打印出来的是POINT

2.由于cpp已经指向了c+2,所在进行++cpp,就又指向了c+1,对他进行解引用找到了c+1的地址再进行--,所以c+1变为了(c+1-1)得到c,再进行解引用找到了ENTER首字符的地址,再进行+3,跳过三个字节,所以打印出来的是ER

3.由于cpp已经指向了c+1,而那个c+1地址又已经变为了c的地址,所以cpp[-2]本质为*(cpp-2)找到了c+3的地址再进行解引用得到了FIRST首字符的地址,再进行+3跳过了三个字节,所以打印出来的是ST

4.由于cpp已经指向了c+1,而那个c+1地址又已经变为了c的地址,所以cpp[-1][-1]本质为

*(*(cpp-1)-1)找到了NEW首字符的地址,再进行+1跳过一个字节,所以打印出EW

小编的分享到这里就结束了!如果有什么不足的地方,请大佬们指点,小编一定吸取教训,将文章质量提高!!! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/155557.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ffmpeg 颜色空间转换分析

颜色空间转换有很多相关标准&#xff1a; https://docs.opencv.org/3.4.0/de/d25/imgproc_color_conversions.html https://www.itu.int/rec/R-REC-BT.601-4-199407-S/en ffmpeg命令行颜色空间转换是通过调用vf_scale中的swscale来进行转码。 我们通过gdb来调试ffmpeg. 首先编译…

《Getting Started with NLP》chap11:Named-entity recognition

《Getting Started with NLP》chap11&#xff1a;Named-entity recognition 最近需要做一些NER相关的任务&#xff0c;来学习一下这本书的第十一章 文章目录《Getting Started with NLP》chap11&#xff1a;Named-entity recognition11.1 Named entity recognition: Definition…

jar转成dex文件

jar转成dex文件 dx 可以利用android studio中的dx工具。 可以看到android的tool安装位置: 在此路径下的如下目录有dx.bat,这个正是我们需要使用的工具。 D:\sdk\build-tools\30.0.3将dx.bat添加到环境变量 基本指令 > dx --dex --output 输出路径 待转化的jar包C

高性能网络模式:Reactor 和 Proactor

文章目录演进多 Reactor 多进程 / 线程Proactor总结演进 如果要让服务器服务多个客户端&#xff0c;那么最直接的方式就是为每一条连接创建线程。其实创建进程也是可以的&#xff0c;原理是一样的&#xff0c;进程和线程的区别在于线程比较轻量级些&#xff0c;线程的创建和线…

【Dash搭建可视化网站】项目12:全球恐怖主义数据大屏制作步骤详解

全球恐怖主义数据大屏制作步骤详解1 项目效果图2 项目架构3 文件介绍和功能完善3.1 assets文件夹介绍3.2 app.py和index.py文件完善3.3 header.py文件完善3.4 filteritem.py文件完善3.5 api.py文件和api.ipynb文件完善3.6 staclbarline.py文件完善3.7 piechart.py文件完善3.8 m…

IO多路复用之select、poll、epoll之间的区别总结

一、IO多路复用基本概念 select、poll、epoll都是IO多路复用的机制。IO多路复用就是通过一种机制&#xff0c;让一个进程/线程可以监视多个描述符&#xff0c;一旦某个描述符就绪&#xff08;一般是读写就绪&#xff09;&#xff0c;能够通知应用程序进行相应的读写操作。 I/…

并网逆变器学习笔记5---三电平DPWM

参考文献&#xff1a;《中压三电平全功率风电变流器关键技术研究---任康乐》 1、调制策略分析 DPWM由于其在任意时刻均有一相钳位在某个电平&#xff0c;使得该相的功率器件不发生开关动作&#xff0c;因而可以大大降低开关损耗&#xff08;平均降低1/3&#xff09;&#xff…

Java多线程案例——定时器

一&#xff0c;定时器1.定时器的概念定时器是Java开发中一个重要的组件&#xff08;功能类似于闹钟&#xff09;&#xff0c;可以指定一个任务在多长时间后执行&#xff08;尤其在网络编程的时候&#xff0c;如果网络卡顿很长时间没有响应用户的需求&#xff0c;此时可以使用定…

分享|UWB使用频段大幅收窄,新标准对于行业发展是好是坏?

近日&#xff0c;工信部无线电管理局发布了《超宽带&#xff08;UWB&#xff09;设备无线电管理规定&#xff08;征求意见稿&#xff09;》&#xff08;以下简称“新版《规定》”&#xff09;。 根据新版《规定》&#xff0c;未来国内UWB技术的使用频段为&#xff1a;7235-875…

seo的基本知识(概述网站内部优化和外部优化)

了解网站外部优化的4大重点 网站优化的时候都会重视网站的外部优化&#xff0c;所以网站外部优化的4大重点&#xff01;今天就来和大家说一说&#xff01; 1.高质量的内容和外链 未来的SEO道路高质量的有价值的内容是非常重要的&#xff0c;还有就是高质量的外链也是重要之…

北大硕士LeetCode算法专题课-查找相关问题

黑马算法面试专题 北大硕士LeetCode算法专题课-字符串相关问题 北大硕士LeetCode算法专题课-数组相关问题_​​​​​​ 北大硕士LeetCode算法专题课-基础算法查找_ 北大硕士LeetCode算法专题课-基础算法之排序_客 北大硕士LeetCode算法专题课---算法复杂度介绍_…

Neo4j框架学习之一安装和使用

文章目录1、何为Neo4j2、安装和使用2.1 安装2.2 基础概念1、何为Neo4j ​ Neo4j是一个高性能的NOSQL图形数据库&#xff0c;是一个嵌入式的、基于磁盘的&#xff0c;数据结果为网格(图)、具备完全的事务特性的Java持久化引擎。 数据结构 ​ 在一个图中包含两种基本的数据类型…

从浏览器里输入URL构建你的前端知识体系

嗨&#xff01;我是团子&#xff0c;好久不见~ 记得22年寒假复习八股的时候&#xff0c;一直在苦恼怎样才能把八股的内容真正的转换为自己的知识。毕竟光靠死记硬背每个知识点&#xff0c;是不能在面试中给面试官留下不错的印象的。后面在整理《浏览器里输入URL后发生了什么》…

Stellarium 1.2 正式发布

导读Stellarium 1.2 已发布。Stellarium 是一款免费开源 GPL&#xff08;自由软件基金会 GNU 通用公共许可证&#xff09;软件&#xff0c;它使用 OpenGL 图形接口对星空进行实时渲染。 软件可以模拟肉眼、双筒望远镜和小型天文等观察天空&#xff0c;根据观测者所处时间和位置…

项目管理:项目经理如何创建项目日程计划表

当项目经理接手项目后&#xff0c;要做好项目的日程安排&#xff0c;这是决定项目是否成功完成的最重要任务之一。 项目经理都希望项目按照制定好的进度计划完工&#xff0c;但在实际的情况中&#xff0c;总会有那么一两个项目会出现进度延迟的情况&#xff0c;管理者可以使用…

忆享科技戟星安全实验室|OSS的STS模式授权案例

戟星安全实验室忆享科技旗下高端的网络安全攻防服务团队.安服内容包括渗透测试、代码审计、应急响应、漏洞研究、威胁情报、安全运维、攻防演练等。本文约957字&#xff0c;阅读约需3分钟。前言《漏洞挖掘系列》将作为一个期刊持续更新&#xff0c;我们会将项目中所遇到的觉得有…

图像编辑Photoshop 2023中文新

Photoshop2023从照片编辑和合成到数字绘画、动画和图形设计-只要能想到&#xff0c;就能在Photoshop中创作出来。相信大家都有在用之前的版本&#xff0c;这款软件功能丰富&#xff0c;实用性很强&#xff0c;有着大量的功能用户都可以用上&#xff0c;不管是美化还是滤镜&…

基于冲突搜索(CBS)的多智能体路径寻优(MAPF)

1 背景 1.1 问题描述 多智能体路径寻优( Multi-Agent Path Finding&#xff0c;MAPF )问题由一个无向无权图G ( V &#xff0c;E )和一组k个智能体组成&#xff0c;其中智能体有起始点和目标点。时间被离散化为时间步。在连续的时间步之间&#xff0c;每个智能体既可以移动到…

Kafka生产者——消息发送流程,同步、异步发送API

生产者消息发送流程 发送原理 Kafka的Producer发送消息采用的是异步发送的方式。 在消息发送的过程中&#xff0c;涉及到了两个线程:main线程和Sender线程&#xff0c;以及一个线程共享变量:RecordAccumulator。 ①main线程中创建了一个双端队列RecordAccumulator&#xff0c…

Spring Boot 创建和使用

Spring Boot 创建和使用一、什么是 Spring Boot二、Spring Boot 优点三、Spring Boot 项目创建3.1 使用 Idea 创建验证3.2 网页版创建四、项目目录介绍五、约定大于配置 (重要)5.1 启动类5.2 自定义类在目录中的位置一、什么是 Spring Boot Spring 的诞⽣是为了简化 Java 程序…