指针笔试题(C语言进阶)

news2024/9/22 22:30:52

目录

前言

1、案例一

1.1 答案

1.2 解析

2、案例二

2.1 答案

2.2 解析

3、案例三

3.1 答案

3.2 解析 

4、案例四

4.1 答案

4.2 解析

5、案例五

5.1 答案

5.2 解析

总结


前言

        “纸上得来终觉浅,绝知此事要躬行”。本篇通过对指针实际案例的分析,由浅入深,来加强我们对指针的理解。

1、案例一

#include <stdio.h>
int main()
{
	int a[5] = { 1,2,3,4,5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));
	return 0;
}

        先自己想想,下面公布答案。

1.1 答案

        答案是2,5。

1.2 解析

        其实第一个输出的2比较好理解,主要是第二个输出可能会有疑问。

        对于*(a+1),本身a表示数组的首元素地址,a+1表示数组的第二个元素的地址,因此解引用a+1得到的结果就是数组的第二个元素的值:2。(解引用就是*)

        对于*(ptr-1),首先我们看看ptr是什么,前面定义 ptr = (int*)(&a + 1); 首先,&a表示将整个数组的地址取出来,其类型为 (int*)[5],大小是5个整型的大小,所以&a+1直接跳过整个数组,指向数组后面一个位置的地址,但是最后又通过(int*)强制将其转化成了int*类型,步长变回一个整型的大小,所以ptr其实就是指向数组最后一个元素后面一个位置地址的指针,类型为(int*)类型,步长为1个整型数据的大小。因此,输出时,ptr-1其实只往回跳了一个整型大小的长度,指向了数组第五个元素(最后一个元素),再解引用得到的答案就是5啦。

2、案例二

#include <stdio.h>
struct Test
{
	int Num;
	char* pcName;
	short cha[2];
	short sBa[4];
}*p = (struct Test*)0x100000;
//假设p 的值为0x100000。如下表达式的值分别为多少。
//已知,结构体Test类型的变量大小是20字节。
//x86环境
int main()
{
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

        这是一道结构体指针的运算,定义结构体*p,其值设定为0x100000。在x86环境下,进行了三种不同的运算,分析结果。

2.1 答案

        答案是:00100014   00100001  00100004

2.2 解析

        对于 p+0x1,是将结构体指针p+1,由于p是结构体指针,所以,其步长为1个结构体的长度,题目说这样一个结构体长度为20(其实可以通过自己计算结构体的内容得出),所以加1直接跳过20个字节,因此输出结果为00100014。(16进制20就是14)。

        对于(unsigned long)p + 0x1,将p强制转换成了无符号长整型,p已经不再是指针,变成了一个长整型1,048,567。加1变成1,048,568。输出时用的%p,也就是地址类型的输出,因此是16进制,1,028,568转换回16进制就是00100001。

        对于(unsigned int*)p + 0x1,将p转化成了无符号整型指针,那其步长就变为了4,p+1就指向4字节后的地址,因此对p+1输出结果为00100004。

3、案例三

        

#include <stdio.h>
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;
}

       %x代表16进制输出,来想想这题的答案吧

3.1 答案

        怎么样,算对了吗?

3.2 解析 

        这道题难点在第二个输出,下面我们一个个分析:

        对于ptr1来说,定义时,(int*)(&a + 1);&a取出了整个数组的地址,+1跳过整个数组指向数组最后一个元素后面一个位置的地址, 然后再将它强制类型转换回(int*)类型,步长变回一个整型数据的大小。输出时,ptr[-1]其实就是输出ptr前一个地址的访问值,ptr前一个地址指向的就是数组最后一个元素,因此输出为4.

        对于ptr2来说,定义时,(int*)((int)a + 1);先将a强制转换成int类型,已经不是指针了,因此+1就是存粹往a上加个1。

        在内存中a[4]的存放是如上图的,强制类型转换后+1指向的其实是如上图的位置,那么再对其进行解引用得到的就是02000000(因为我们用的编译器是小端存储,数据的低位是放在地址的低位的,存储时反着存,读取时要反着读取)

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;
}

4.1 答案

        

        答案是1,是不是没想到

4.2 解析

        其实这题在初始化是有坑的,仔细看我们在初始化的时候用到了(),我举个例子:

(0,1)这个式子其实就是1,这是个逗号表达式,逗号表达式的值就是最后一个','后面的那个值,在这里就是1.其实a[3][2]这个数组只初始话了3个值{1 , 3 , 5}。

        好了,现在再来分析p指针,对于p来讲,p=a[0],将a第一行赋值给p其实就是第一行元素的首地址给了p,最后打印时p[0]其实就是访问a第一行第一个元素的值,相当于a[0][0],最后打印出来就是1。

5、案例五

#include <stdio.h>
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;
}

5.1 答案

答案是:FFFFFFFC,-4

5.2 解析

        这题,p是一个数组指针,其步长为4个整型数据大小,比a数组的每一行长度少1个整型数据大小,p和a一开始指向的是同一个地址,每当p+1时,p只能跳过4个整型数据大小的地址,而对于a来说,a+1可以跳过5个整型数组的大小的地址。所以,p[4][2]和a[4][2]比较,它们都跳过了4行,因此a[4][2]在地址上比p[4][2]多4个整型大小的值,而我们知道,指针和指针相减,得到的是两个指针之间的元素个数,因此是-4,%p是输出地址,其没有原码反码补码的概念,直接将内存中-4的补码输出,就是FFFFFFFC。

总结

        本篇通过五个例子来加强我们对指针和数据存储的理解,希望对你学习c语言的指针有所帮助!

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

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

相关文章

【Spring】SpringBoot 创建和使用

目 录 一.什么是Spring Boot&#xff1f;为什么要学Spring Boot&#xff1f;二.Spring Boot 优点三.Spring Boot 项目创建3.1 使用 Idea 创建3.2 网页版创建注意事项&#xff1a;包路径错误小结&#xff1a;约定大于配置 一.什么是Spring Boot&#xff1f;为什么要学Spring Boo…

算法沉淀——穷举、暴搜、深搜、回溯、剪枝综合练习二(leetcode真题剖析)

算法沉淀——穷举、暴搜、深搜、回溯、剪枝综合练习二 01.括号生成02.组合03.目标和04.组合总和 01.括号生成 题目链接&#xff1a;https://leetcode.cn/problems/generate-parentheses/ 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有…

【JS逆向学习】同花顺(q.10jqka)补环境

逆向目标 目标网址&#xff1a;https://q.10jqka.com.cn/ 目标接口&#xff1a; https://q.10jqka.com.cn/index/index/board/all/field/zdf/order/desc/page/3/ajax/1/ 目标参数&#xff1a;cookie 逆向过程 老规矩&#xff0c;先分析网络请求&#xff0c;发现是 cookie 加…

MySQL 8.0.36 WorkBench安装

一、下载安装包 百度网盘链接&#xff1a;点击此处下载安装文件 提取码&#xff1a;hhwz 二、安装&#xff0c;跟着图片来 选择Custom,然后点Next 顺着左边框每一项的加号打开到每一个项的最底层&#xff0c;点击选中最底层的项目&#xff0c;再点击传过去右边的绿色箭头&a…

光伏智慧化运维系统:实现一站式光伏服务前沿探索

随着全球能源结构的转型&#xff0c;光伏发电已成为绿色能源的重要组成部分。然而&#xff0c;光伏企业的运营和管理却面临着诸多挑战&#xff0c;如方案设计慢、运行状况难以实时掌握、收资效率低等。为解决这些问题&#xff0c;光伏智慧化运维系统应运而生&#xff0c;以其一…

2024牛客(4)K题

登录—专业IT笔试面试备考平台_牛客网 using i64 long long; using ll long long; constexpr ll M 1e9 7; template<class Info> struct SegmentTree {int n;std::vector<Info> info;SegmentTree() : n(0) {}SegmentTree(int n_, Info v_ Info()) {init(n_, …

学习笔记-Git

Git 问题一描述解决方法注意事项 问题一 描述 在commit和push的时候因为网络太慢了中途强行关闭了进程&#xff0c;而push的内容因为文件过大导致无法正常push 按照原本的流程在push的时候会提示失败&#xff0c;并且需要在解决了大文件之后重新push 而因为中途中断了&#x…

GitHubApp大集结!GSYGithubAppFlutter带你飞越编程世界!

GitHubApp大集结&#xff01;GSYGithubAppFlutter带你飞越编程世界&#xff01; GSYGithubAppFlutter是一个功能丰富、跨平台的开源GitHub客户端应用程序&#xff0c;基于Flutter框架开发。该项目属于GSYGithubApp系列&#xff0c;目前已经拥有Flutter、Weex、ReactNative和Ko…

Microsoft PowerToys:自定义 Windows 的实用程序

Microsoft PowerToys&#xff1a;自定义 Windows 的实用程序 Microsoft PowerToys 是一组实用程序&#xff0c;供高级用户调整和简化其 Windows 体验以提高工作效率。 微软官方地址为&#xff1a;https://learn.microsoft.com/en-us/windows/powertoys/&#xff0c;其github源…

防火墙内容安全笔记

目录 DFI和DPI IDS和IPS 签名 AV URL过滤 HTTPS过滤 内容过滤 文件类型过滤 文件内容过滤 邮件过滤 VPN概述 DFI和DPI DFI和DPI技术 --- 深度检测技术 DPI DPI --- 深度包检测技术 --- 主要针对完整的数据包&#xff08;数据包分片&#xff0c;分段需要重组&#…

Spring的copy属性

Spring 的 BeanUtils.copyProperties()实现的是浅拷贝 ClassA public class ClassA {private Integer age;private String name;private ClassC c;public Integer getAge() {return age;}public void setAge(Integer age) {this.age age;}public String getName() {return n…

【stm32】hal库-双通道ADC采集

【stm32】hal库-双通道ADC采集 CubeMX图形化配置 程序编写 /* USER CODE BEGIN PV */ #define BATCH_DATA_LEN 1 uint32_t dmaDataBuffer[BATCH_DATA_LEN]; /* USER CODE END PV *//* USER CODE BEGIN 2 */lcd_init();lcd_show_str(10, 10, 24, "Demo14_4:ADC1 ADC2 S…

vue大文件读取部分内容,避免重复加载大文件,造成流量浪费

使用场景&#xff1a;项目点云地图是pcd文件&#xff0c;但是文件可能上百兆&#xff0c;我需要获取到文件中的版本信息&#xff0c;跟本地的缓存文件做比较&#xff0c;如果不一致&#xff0c;才会加载整个文件。从而节省流量。 避免重复加载整个“.pcd文件&#xff0c;以最大…

2.21数据与结构算法学习日记(最小生成树prim算法)

目录 最小生成树prim 最小生成树算法是一种用来在一个加权连通图中找到最小生成树的算法。最小生成树是一个包含图中所有顶点的树&#xff0c;其总权值最小。 prim算法 洛谷题目示例 P3366 【模板】最小生成树 题目描述 输入格式 输出格式 输入输出样例 说明/提示 题…

郑板桥的人生境界是难得糊涂

郑板桥是康熙秀才&#xff0c;雍正举人&#xff0c;乾隆进士。 郑板桥小时候跟父亲在真州读书&#xff0c;长大后在真州教书。后来&#xff0c;郑板桥去扬州卖画谋生。 郑板桥没有老师&#xff0c;画画靠自己琢磨。郑板桥一生画竹&#xff0c;画了四十年的竹子&#xff0c;主…

【析】考虑同时取送和时间窗的车辆路径及求解算法

期刊&#xff1a;computer engineering and applications 计算机工程与应用![c 引言 1. 问题分析 1.1 问题描述 问题描述为&#xff1a; 若干运输车辆从配送中心出发为客户取送货并最终返回配送中心&#xff0c;每位客户仅由一辆车服务一次&#xff0c;车辆在配送过程中任…

《图解设计模式》笔记(二)交给子类

三、Template Method模式&#xff1a;将具体处理交给子类 示例程序类图 public static void main(String[] args) {// 生成一个持有H的CharDisplay类的实例AbstractDisplay d1 new CharDisplay(H);// 生成一个持有"Hello, world."的StringDisplay类的实例AbstractD…

11-树-二叉树的前序遍历

这是树的第11篇算法&#xff0c;力扣链接。 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3] 做了这么久的树问题&#xff0c;现在开始回忆三种遍历方法&#xff0c;这篇文章…

C#上位机与三菱PLC的通信06--MC协议之QnA-3E报文测试

1、A-3E报文回顾 1、存储区分类及访问规则 2、命令类型 命令由主命令子命令组成 3、报文结构 2、启动mc服务器 3、创建VS项目 这节继续使用上节的VS2022的项目&#xff0c;增加一个方法 MCTestA3E()&#xff0c;具体怎么创建项目&#xff0c;见上节的过程。C#上位机与三菱…

Spring Security学习(六)——配置多个Provider(存在两种认证规则)

前言 《Spring Security学习&#xff08;五&#xff09;——账号密码的存取》一文已经能满足一般应用的情况。但实际商业应用也会存在如下的情况&#xff1a;用户提交的账号密码&#xff0c;能在本地的保存的账号密码匹配上&#xff0c;或者能在远端服务认证中匹配上&#xff…