【C语言】指针练习篇(下),深入理解指针---指针练习题【图文讲解,详细解答】

news2024/12/23 4:37:50

 欢迎来CILMY23的博客喔,本期系列为【C语言】指针练习篇(下),深入理解指针---指针练习题【图文讲解,详细解答】,图文讲解指针练习题,带大家更深刻理解指针的应用,感谢观看,支持的可以给个赞哇。

前言

作为指针系列的番外练习篇,本篇主要以指针练习题为主,本期博客将上期未写的二维数组开头,并且以做题的视角带入,进行深刻理解指针练习题中不同用法区别。 

二、指针,数组笔试题 

 2.3二维数组

	int a[3][4] = { 0 };

	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a[0][0]));
	printf("%d\n", sizeof(a[0]));
	printf("%d\n", sizeof(a[0] + 1));
	printf("%d\n", sizeof(*(a[0] + 1)));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(*(a + 1)));
	printf("%d\n", sizeof(&a[0] + 1));
	printf("%d\n", sizeof(*(&a[0] + 1)));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a[3]));

x86环境结果如下:

x64环境结果如下:

2.3解析:

     printf("%d\n", sizeof(a));

a单独放在sizeof后面,计算的是整个数组的大小,大小3*4*4 = 48字节
    printf("%d\n", sizeof(a[0][0]));

a [0][0],表示的是数组第1行第1列元素,元素是0,计算大小是整型,大小为4字节
    printf("%d\n", sizeof(a[0]));

a[0] 表示的是数组第一行的数组名,单独放在sizeof后面,计算的是一个一维数组的大小,大小为4*4 = 16字节
    printf("%d\n", sizeof(a[0] + 1));

a[0] 表示的是数组第一行的数组名,因为并没有单独放在sizeof后面,所以数组名表示数组首元素的地址,也就是a[0][0]的地址, a[0] + 1  == *(a+0) + 1 是第一行第二个元素的地址,是地址,大小就为4/8字节
    printf("%d\n", sizeof(*(a[0] + 1)));

 根据上面解释,解引用后得到的解释第一行第二个元素,数据类型是整型,所以大小为4字节
    printf("%d\n", sizeof(a + 1));

 a并没有单独放在sizeof后面,没有&,所以表示数组首元素的地址,即a[0],+1后就表示a[1]的地址,是地址就为4/8字节
    printf("%d\n", sizeof(*(a + 1)));

根据上面所说,得到的就是a[1]所对应的元素,计算的是整个一维数组的大小,数据类型是int,所以大小为4*4 = 16字节
    printf("%d\n", sizeof(&a[0] + 1));

&a[0]表示将第一行的数组地址取出来,+1就是跳过整个数组,表示的是a[1]的地址,是地址大小为4/8字节
    printf("%d\n", sizeof(*(&a[0] + 1)));

同上所述,解引用后计算的是a[1]整个数组的大小,大小为4*4=16字节
    printf("%d\n", sizeof(*a));

a是数组首元素的地址,也就是数组第一行(a[0])的地址,解引用计算的是 a[0],计算的是一个一维数组的大小,大小为4*4 = 16。

*a == *(a+0) == a[0]
    printf("%d\n", sizeof(a[3]));

因为sizeof是根据类型推断的,所以它不会实际访问,在这里a[3]  == a[0],所以大小为4*4 = 16

三、指针运算笔试题

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

结果如下:

 解析:

&a 表示取出整个数组的地址,+1后表示指向五后面的地址,将其整体转换成int *类型存入,ptr指针变量中,所以ptr此刻指向的是五的末尾,(a+1),a是数组名,并没有单独放在sizeof后面,也没有&操作符,所以表示数组首元素地址,+1指向数组第二个元素的地址,解引用得到2,ptr - 1,跳过的是指针类型,ptr的指针类型是int * 类型,所以跳过4个字节,指向五的前面,解引用得到5,所以答案为2,5

3.2

#include<stdio.h>
//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结构是啥?
struct Test
{
	int Num;
    char* pcName; 
    short sDate; 
    char cha[2];
    short sBa[4];
 }*p = (struct Test*)0x100000;

int main()
{
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1); 
	printf("%p\n", (unsigned int*)p + 0x1); 
    return 0;	
}

结果:

解析:考点是指针加减整数,不懂的可以看入门篇http://t.csdnimg.cn/n6szR

第一个,p+0x1 ,首先0x1,转换成十进制是加1,p是指针变量,加一跳过一个指针类型的大小,p的指针类型是结构体类型,大小为20,故答案是0x100014(原先的十六进制加二十)

第二个, p不是指针,所以p如果加1,就是简单的值相加,故原先的十六进制加1,答案为0x100001

第三个,p是unsigned int*类型的指针变量,指针变量+1,跳过一个unsigned int*类型大小,故加4,0x100004

3.3

#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,3,5};

所以 int a[3][2] = { 1,3,5} 

所以打印结果为1

3.4

//假设环境是x86环境,程序输出的结果是啥?
#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;
 }

结果如下:

解析:考点为指针减指针,不懂的可以看入门篇http://t.csdnimg.cn/n6szR

int (*p)[4]是一个数组指针,如果把a放入p中,就相当于用p给a数组划分区域了。

它们中间相差四个元素,相减完得到-4.

如果用%p打印-4,就打印地址,就是用二进制表示-4,%d就是直接打印-4

FFFFFFFC,-4

3.5

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

结果如下: 

 解析:

&aa + 1,aa是数组名,放在&后面,表示取出整个数组的地址,+1表示指向10的末尾的地址,将其转换成int * 类型,放入ptr1

(aa + 1) aa是数组名,没有单独放在sizeof后面,也没有&操作符,所以表示数组首元素地址,aa[0]. +1后表示a[1]的地址。将其解引用后,就表示a[1]。将其存入ptr2 减一后指向的位置就是5.

所以答案就为10和5

aa分布图如下:

3.6

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

结果如下:

  

解析:

char* a[]  是一个指针数组,当中存放的是w a a的地址,我们用一个二级指针pa来指向a这个数组,pa++后指向的是中间区域,解引用后得到的就是at

3.7

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

结果如下:

 

解析: 

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

**++cpp,此刻cpp先加后用,cpp指向cp的第二个元素,也就是c+2的位置,解引用第一层,获得p的地址,再解引用后,得到POINT

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

* -- *++ cpp + 3  首先看++cpp,指向C+2这个位置,++cpp后,指向c+1这个位置,解引用后,再--,指向E这个位置,解引用后+3,指向的是T后面E前面,所以打印ER

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

cpp[-2] == *(cpp-2),所以此刻cpp指向的位置是C+3,解引用后得到F所指向的位置,+3后指向S的前面,最后打印,得到ST
    printf("%s\n", cpp[-1][-1] + 1);

cpp[-1][-1] === *(*(cpp -1) -1), cpp指向的位置是c+1,减一后指向c+2,解引用后指向p,然后减一,指向N,最后解引用再+1,指向E前面,所以打印EW

图如下所示

感谢各位同伴的支持,本期指针练习篇(下)就讲解到这啦,如果你觉得写的不错的话,可以给个赞,若有不足,欢迎各位在评论区讨论。    

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

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

相关文章

ctfshow-web29~40-WP

web29 if(isset($_GET[c])){$c = $_GET[c];if(!preg_match("/flag/i", $c)){eval($c);}}else{highlight_file(__FILE__); } 首先先system(“ls”);查看一下文件 既然过滤了flag,那我们就fla*的形式进行匹配,结合tac命令输出flag.php文件内容

舵机PID控制

目录 舵机工作原理 舵机PID控制 原理介绍 代码 主代码 赋值PWM寄存器 限制PWM赋值 取绝对值 位置式PID控制 位置式离散PID 舵机工作原理 控制电路接收信号源的控制脉冲&#xff0c;并驱动电机转动&#xff1a;控制电路接收来自遥控器或者单片机的控制信号&#xff0c;然后驱…

milligram css 源码浅析

一、前言 milligram 是我在 20 年接触并使用的一个 CSS 库&#xff0c;他的出现时间已经无法溯源了&#xff0c;根据 npm 上的发布时间最早是 2015 年&#xff0c;而在国内名气起来的时间大概就是 2020 年了&#xff0c;同时 milligram 最后的更新也停在了那一年。 由于当时只…

[工具探索]VSCode介绍和进阶使用

相比较GoLand、PhpStorm、PyCharm、WebStorm的重量级内存占用&#xff0c;从Windows系统来&#xff0c;各种卡死&#xff0c;换到MacOS倒不会卡死&#xff0c;但是内存占用太多&#xff0c;影响体验&#xff0c;决定换到VSCode。当然这个过程需要适应过渡期&#xff0c;旧伙计都…

C++入门 上(命名空间 缺省参数 函数重载)

C入门 上 命名空间命名空间定义命名空间使用 C输入输出缺省参数缺省参数概念缺省参数分类 函数重载函数重载概念C支持函数重载的原理--名字修饰 命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存在于全局作用…

阿里云服务器部署配置选择全攻略

阿里云服务器配置怎么选择&#xff1f;根据实际使用场景选择&#xff0c;个人搭建网站可选2核2G配置&#xff0c;访问量大的话可以选择2核4G配置&#xff0c;企业部署Java、Python等开发环境可以选择2核8G配置&#xff0c;企业数据库、Web应用或APP可以选择4核8G配置或4核16G配…

ActiveMQ高可用架构涉及常用功能整理

ActiveMQ高可用架构涉及常用功能整理 1. activemq的集群模式2. 镜像模式高可用系统架构和相关组件2.1 架构说明2.2 相关概念说明2.3 消息模型2.3.1 点对点2.3.2 发布订阅 3. activemq常用命令4. activemq配置集群5. 疑问和思考5.1 activemq的数据删除策略是怎样的&#xff1f;5…

已解决:IDEA中@Autowired自动注入MyBatis Mapper报红警告的几种解决方法

今天在使用 IDEA 使用 MyBatis 的时候遇到了这种情况&#xff1a; 可以看到 userMapper 下有个红色的波浪警告&#xff0c;虽然代码没有任何问题&#xff0c;能正常运行&#xff0c;但是这个红色警告在这里杵着确实让人很窝心。 于是我在网上找了找&#xff0c;最终明白了原因…

使用静态CRLSP配置MPLS TE隧道

正文共&#xff1a;1591 字 13 图&#xff0c;预估阅读时间&#xff1a;4 分钟 静态CRLSP&#xff08;Constraint-based Routed Label Switched Paths&#xff0c;基于约束路由的LSP&#xff09;是指在报文经过的每一跳设备上&#xff08;包括Ingress、Transit和Egress&#xf…

DBeaver通用数据库管理 连接DM8 数据库及其配置

一.工具版本说明 DBeaver版本: 21.0.202106012023&#xff0c; 推荐官网下载。 DM8/达梦数据库: DM 8 Windows 官网安装手册 如果想深入了解DM8 数据库操作请参考&#xff1a;DM8/达梦 数据库管理员使用手册详解 二.DM8/达梦驱动下载 下载渠道/官方文档 DM 8/达梦技术…

LeetCode JS专栏刷题笔记(一)

一、前言 LeetCode 在前不久出了一个 JavaScript 专栏&#xff0c;这个专栏一个目的是为了非前端工程师学习 JS&#xff0c;另一个是为了前端工程师提升 JS 能力。 因此在这个专栏中&#xff0c;基本不涉及什么具体算法问题&#xff0c;都是一些 JS 的入门语法与常见的 JS 面…

Maven(基础)、MyBatis

简介 Apache Maven是一个项目管理和构建工具&#xff0c;它基于项目对象模型 (POM)的概念&#xff0c;通过一小段描述信息来管理项目的构建、报告和文档 官网: http://maven.apache.org/ Maven作用 Maven是专门用于管理和构建Java项目的工具&#xff0c;它的主要功能有&#x…

Elasticsearch查询报错 Result window is too large

一现象&#xff1a; es数据分页查询前端提示系统异常&#xff0c;后端报错日志 二根本原因&#xff1a; 默认情况下&#xff0c;Elasticsearch 限制了 from size 参数的组合不能超过 10,000 条记录&#xff0c;用于防止查询大数据集时对系统资源的过度消耗 三解决办法&#…

JavaSE——面向对象基础(1/4)-面向对象编程、程序中的对象、对象的产生、对象的执行原理、类和对象的一些注意事项

目录 面向对象编程 程序中的对象 对象的产生 对象的执行原理 类和对象的一些注意事项 面向对象编程 开发一个一个的对象&#xff0c;把数据交给对象&#xff0c;再调用对象的方法来完成对数据的处理。 例如设计一个学生的对象&#xff0c;其中有姓名和成绩等&#xff0c…

可视化视频监控平台EasyCVR如何配置服务参数以免getbaseconfig接口信息泄露?

可视化云监控平台/安防视频监控系统EasyCVR视频综合管理平台&#xff0c;采用了开放式的网络结构&#xff0c;平台支持高清视频的接入和传输、分发&#xff0c;可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集…

【.NET Core】C#编程规范

【.NET Core】C#编程规范 文章目录 【.NET Core】C#编程规范一、概述1.1 结构清晰第一1.2 简洁之风1.3 代码风格保持一致性 二、命名约定三、类型参数命名指南3.1 请使用描述性名称命名泛型类型参数&#xff0c;除非单个字面名称完全具有自我说明性且描述性名称不会增加任何作用…

Redis(03)——发布订阅

基础命令 基于频道 publish channel message&#xff1a;将信号发送到指定的频道pubsub subcommand [argument [argyment]]&#xff1a;查看订阅或发布系统状态subscribe channel [channel]&#xff1a;订阅一个或多个频道的信息unsubscribe [channel [channel]]&#xff1a;退…

CSS:BFC

BFC&#xff0c;Block Formatting Context&#xff0c;块级格式化上下文&#xff0c;是一个独立的渲染区域或隔离的独立容器&#xff0c;它决定了其子元素如何布局&#xff0c;并且与这个区域外部的元素无关。 形成 BFC 的条件 float 的值不为 none&#xff08;left、right&a…

【Node.js和Appium server的下载安装步骤】

Node.js 是JavaScript的运行环境&#xff0c;是 JS 语言的解释器&#xff0c;之中集成了npm库。 npm 是世界上最大软件包仓库&#xff0c;可用于Appium server安装。 1、Node.js官方安装包及源码下载地址&#xff1a;Node.js 选择相应系统的安装包进行下载&#xff08;.msi用…

c编译器学习02:chibicc文档翻译

目的 先粗略地看一遍作者的书籍。 原文档地址 https://www.sigbus.info/compilerbook# “低レイヤを知りたい人のためのCコンパイラ作成入門” 为想了解底层的人准备的C编译器制作入门 Rui Ueyama ruiucs.stanford.edu 2020-03-16 作者简介 https://www.sigbus.info/ 植山…