E31.【C语言】练习:指针运算习题集(上)

news2024/9/19 10:36:41

Exercise 1

求下列代码的运行结果

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

答案速查:

分析:

Exercise 2

 求下列代码的运行结果

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

答案速查:

分析:

☑ printf("%p\n", p + 0x1);

出现单个p,代表结构体中首元素的地址,类比&数组名,+0x1跳过整个结构体

十进制20=0x14

即0x100000+0x14==0x100014,x86环境下输出结果为00100014

☑ printf("%p\n", (unsigned long)p + 0x1);

 p被强制类型转换为unsigned long,p不再是struct Test*指针类型(不考虑+0x1跳过整个结构体)即0x100000+0x1=0x100001,x86环境下输出结果为00100011

☑ printf("%p\n", (unsigned int*)p + 0x1);

p被强制类型转换为unsigned long*指针类型,之前讲过,指针+1表示跳过4个字节,即

0x100000+4==0x100004,x86环境下输出结果为00100004

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

答案速查:

分析:

错误思路:

认为二维数组的元素排布是这样的:

在13.5.【C语言】二维数组里讲过:只有这样写int a[3][2] = { {0, 1}, {2, 3}, {4, 5} };内部是大括号不是圆括号)才是上方的排布!

写成这样int a[3][2] = { (0, 1), (2, 3), (4, 5) };内含逗号表达式

在15.【C语言】初识操作符 下里讲过

exp1,exp2,exp3,……,expn

程序从左向右依次执行exp

整个exp的结果是最后一个exp的结果

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

画成图是这样的:

回看代码:p[0]即a[0][0],所以输出1

Exercise 4

 求下列代码的运行结果

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

答案速查:

分析:

该数组元素排布图:

在内存中:

int* ptr1 = (int*)(&aa + 1);

\

"&数组名"取的是整个数组的地址,+1跳过整个数组,在*(ptr1-1)又往回4个字节,解引用是10

*(aa+1)相当于aa[1],二维数组的一行就是一维数组,aa代表第一行的地址,+1转到第二行的6,输出*(ptr2-1)解引用是5

结果为10,5

★Exercise 5:指针-指针

求下列代码的运行结果

//假设环境是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;
}

答案速查:

分析:

分析上方代码前先回顾下数组和指针

#include <stdio.h>
int main()
{
	int arr1[5] = { 1,2,3,4,5 };
	int* p1 = &arr1;

    int arr2[5]={ 0 };
	int *p2[5] = &arr2;

    int arr3[5]={ 0 };
	int (*p3)[5] = &arr3;

    int arr4[5]={ 0 };
	int* (*p4)[5] = &arr4;
	return 0;
}

上方代码运行是否有错误?写的是否规范呢?

逐条分析:

int arr1[5] = { 1,2,3,4,5 };定义了一个名为arr1的数组,其类型为int[5]

int* p1 = &arr1;&arr1的类型在int[5]的基础上加个*,即int[5]

这里int[5]int[5]类型不匹配

因此编译器会报警告:

必须强制让*与p1结合,建议改成:

int (*p1)[5] = &arr1;//p1是int(*)[5],指向含五个整型元素的数组

int arr2[5] = { 1,2,3,4,5 };定义了一个名为arr2的数组,其类型为int[5]

int *p2[5] = &arr2;出现了严重的问题!!

报错:

编译器认为p2是数组其包含5个元素(p2[5]),数组的类型为int*

&arr2的类型为int(*)[5]

这里int*int(*)[5]类型不匹配

必须强制让*与p2结合,建议改成:

int (*p2)[5] = &arr2;//p2是int(*)[5],指向含五个整型元素的数组

int arr3[5]={ 0 };int (*p3)[5] = &arr3;写法无误,解释同上


int arr4[5] = { 0 };定义了一个名为arr4的数组,其类型为int[5]

int* (*p4)[5] = &arr4;但p4类型有问题

arr4类型为int[5]

&arr4类型为int(*)[5]

但p4类型为int* (*)[5] 意思是p4是指向含5个int*类型指针元素的数组的指针

所以int(*)[5]int* (*)[5] 类型不匹配

因此编译器会报警告:

建议改成:

int* arr4[5] = { 0 };
int* (*p4)[5] = &arr4;

回到本练习:

a的类型为int[5][5],p的类型为int(*)[4],两者类型不一样,p=a;会发生类型的转换

因此会报警告

二维数组在内存中的排布(图中一个格子代表一个元素)可以按两种形式理解:p形式和a形式

对于p[4][2]:由于p是int(*)[4]类型,p+1代表跳过二维数组(这里p形式的二维数组是每4个元素一行因为int(*)[4])的第一行至第二行,因此p[4][2]即第4行(从第0行开始算)中的第2个元素

对于a[4][2]:由于a是int[5][5]类型,因此是第4行(从第0行开始算)中的第2个元素(这里a形式的二维数组是每5个元素一行)

指针-指针是两个指针之间的元素个数,%p以补码形式打印,%d以原码形式打印

&p[4][2] - &a[4][2]==小-大==负数,所以为-4(原码)-->FFFFFFFC(补码)

结果:FFFFFFFC,-4

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

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

相关文章

使用Ansible stat模块检查目录是否存在

使用Ansible stat模块检查目录是否存在或者是否为一个目录还是文件 理论知识 在Ansible中&#xff0c;你可以使用stat模块来检查一个目录是否存在。stat模块可以用来获取文件或目录的状态信息&#xff0c;包括它是否存在。下面是一个简单的例子&#xff0c;说明如何使用stat模…

9/3作业

一、继承&#xff08;inhert&#xff09; 面向对象三大特征&#xff1a;封装、继承、多态 继承&#xff1a;所谓继承&#xff0c;是类与类之间的关系。就是基于一个已有的类&#xff0c;来创建出一个新类的过程叫做继承。主要提高代码的复用性。 1.1 继承的作用 1> 实现…

GraphRAG工程落地成本详细解读和实例分析

最近半年GraphRAG引起不少关注&#xff0c;。GraphRAG代表了一种创新的方法&#xff0c;用于支持检索增强生成&#xff08;RAG&#xff09;应用&#xff0c;使组织能够从其复杂的数据集中提取前所未有的价值。然而&#xff0c;与大多数组织使用的相对简单的数据嵌入和向量化过程…

mkv怎么转换成mp4?2个简单易用的格式转换方法

小王立志成为一名vlogger&#xff0c;为此&#xff0c;他在旅行的时候拍摄了一段旅游视频&#xff0c;把视频保存在mkv格式中。在平台上传时小王才发现mkv视频不被平台支持。 小王傻眼了&#xff0c;视频需要把mkv转换成mp4格式才能发布&#xff0c;但mkv怎么转换成mp4&#x…

Socket编程---TCP篇

目录 一. TCP协议 二. 服务端模块代码实现 三. 服务端调用模块代码实现 四. 客户端模块代码实现 五. 初始版本结果展示 六. 多进程版服务端 七. 多线程版服务端 八. 线程池版服务端 前文已经讲了UDP的知识&#xff08;点此查看&#xff09;。今天来讲讲…

探索AWS EC2:云计算的强大引擎

在数字化转型的浪潮中&#xff0c;企业对计算资源的需求不断增长。亚马逊弹性计算云&#xff08;EC2&#xff09;作为AWS&#xff08;亚马逊网络服务&#xff09;的核心产品之一&#xff0c;凭借其强大的功能和灵活性&#xff0c;成为了全球企业构建和扩展应用的首选平台。无论…

K8S - 外部访问集群

前言 文档可以承接前面的内容看 这里只做外部访问的介绍 正文 kubectl get po#打印某个pod的环境变量 kubectl exec nginx-7c5ddbdf54-6nfw2 \-- printenv |grep KUBERNETES#删除 service kubectl get svc kubectl delete svc nginx#使用 LoadBalancer 的方式重新创建 servi…

Etherpad在线文档协作编辑工具

Etherpad在线文档协作编辑工具 一、前言 Etherpad是一种开源的实时协作编辑器&#xff0c;允许多个用户同时编辑同一文档&#xff0c;并实时显示每个用户的输入内容。Etherpad最初由Etherpad基金会开发&#xff0c;后来被Google收购&#xff0c;现在由Apache软件基金会维护。E…

ElasticSearch-集群架构

核心概念 节点类型分片集群搭建 ES安全认证 集群内部安全通信 生产环境常见集群部署方式 单一角色增加节点水平扩展读写分离架构异地多活架构Hot & Warm 架构集群容量规划 产品信息库搜索时间序列的数据 核心概念 ES集群架构的优势 提高系统的可用性&#xff0c;部分节点…

【QT】学习笔记:枚举桌面窗口句柄

在 Qt 中&#xff0c;虽然 Qt 本身没有直接提供枚举桌面窗口的 API&#xff0c;但可以通过调用 Windows API 来实现枚举桌面上所有窗口的句柄&#xff0c;包括子窗口以及子窗口与父窗口的关系。我们可以使用 Windows 的 EnumWindows 和 EnumChildWindows 函数来枚举所有顶层窗口…

C语言指针进阶三:(回调函数,qsort函数的模拟)

回调函数 回调函数就是通过函数指针调用的函数&#xff0c;如果你把函数的指针作为参数传递给另一个函数&#xff0c;当这个指针被用来调用其指向的函数时&#xff0c;我们所说这就是回调函数。 qsort函数的使用&#xff08;回调函数案例&#xff09; 我们先看看qsort函数的…

【单调栈 】2289. 使数组按非递减顺序排列

本文涉及的基础知识点 单调栈分类、封装和总结 LeetCode2289. 使数组按非递减顺序排列 给你一个下标从 0 开始的整数数组 nums 。在一步操作中&#xff0c;移除所有满足 nums[i - 1] > nums[i] 的 nums[i] &#xff0c;其中 0 < i < nums.length 。 重复执行步骤&a…

【重磅推荐】《一本书读懂大模型:技术创新、商业应用与产业变革》发布!大模型零基础入门到精通

近日&#xff0c;由中国电信研究院天翼智库大模型研究团队编写、中国电信集团科技委主任邵广禄倾情作序的**《一本书读懂大模型&#xff1a;技术创新、商业应用与产业变革》**正式出版。本书系统介绍了大模型技术的发展历程、核心技术、行业应用、产业体系、治理问题以及未来展…

DeFi 发展的岔路口,Pencils Protocol带领投资者们“向前看”

DeFi 市场是否还存在 Alpha 机会&#xff1f; 走下坡路的 DeFi 去中心化金融&#xff08;DeFi&#xff09;曾是区块链世界发展的起点&#xff0c;也是链上世界流动性的重要支柱。然而&#xff0c;自 2021 年 DeFi 领域的总锁仓量&#xff08;TVL&#xff09;达到历史巅峰——…

模型压缩之剪枝

&#xff08;1&#xff09;通道选择 这里要先解释一下&#xff1a; &#xff08;1&#xff09;通道剪枝 那我们实际做法不是上面直接对所有层都添加L1正则项&#xff0c;而是仅仅对BN层权重添加L1正则项。通道剪枝具体步骤如下&#xff1a; 1.BN层权重添加L1正则项&#xf…

ElementUI实现el-table组件的合并行功能

前言 有时遇到一些需求&#xff0c;需要实现ElementUI中&#xff0c;el-tabled组件合并单元格的功能&#xff0c;稍微了解一下它的数据格式&#xff0c;不难可以写出比合并方法。但是在鼠标经过单元行时&#xff0c;会出现高亮的行与鼠标经过的行不一致的BUG。因此还需要实现c…

超级右键 - 为 Mac 的右键菜单升级一下

是不是有很多小伙伴&#xff0c;希望 Mac 也能像 Windows 一样&#xff0c;拥有丰富的右键菜单&#xff0c;快速完成新建、剪切、发送文件等操作。 一个叫作超级右键的工具就能做到&#xff0c;它能为 Mac 右键菜单增添多个功能选项&#xff0c;如 Win 系统般一键新建 / 剪切文…

vue通过html2canvas+jspdf生成PDF问题全解(水印,分页,截断,多页,黑屏,空白,附源码)

前端导出PDF的方法不多&#xff0c;常见的就是利用canvas画布渲染&#xff0c;再结合jspdf导出PDF文件&#xff0c;代码也不复杂&#xff0c;网上的代码基本都可以拿来即用。 如果不是特别追求完美的情况下&#xff0c;或者导出PDF内容单页的话&#xff0c;那么基本上也就满足业…

我的大模型岗位面试总结!太卷了!!!—我面试了24家大模型岗位 只拿了9个offer!

这段时间面试了很多家&#xff08;共24家&#xff0c;9个offer&#xff0c;简历拒了4家&#xff0c;剩下是面试后拒的&#xff09;&#xff0c;也学到了超级多东西。 大模型这方向真的卷&#xff0c;面试时好多新模型&#xff0c;新paper疯狂出&#xff0c;东西出的比我读的快…

传统CV算法——基于opencv的答题卡识别判卷系统

基于OpenCV的答题卡识别系统&#xff0c;其主要功能是自动读取并评分答题卡上的选择题答案。系统通过图像处理和计算机视觉技术&#xff0c;自动化地完成了从读取图像到输出成绩的整个流程。下面是该系统的主要步骤和实现细节的概述&#xff1a; 1. 导入必要的库 系统首先导入…