C语言——小知识和小细节15

一、二维数组与指针

例一

下面的程序运行结果是什么:

#include <stdio.h>int main()
{int arr[3][2] = { (1,2),(3,4),(5,6) };int* p = arr[0];printf("%d\n", *p);return 0;
}

运行结果:

实际上这里有个小细节,就是二维数组的初始化实际上是不完全初始换,因为,内部用的是小括号,所以这里的 (1,2) (3,4) (5,6) 都是逗号表达式,逗号表达式的结果是最后一个表达式的结果,所以这里的初始化相当于:

int arr[3][2] = { 2,4,6 };

 所以具体的初始化情况:

arr[0] 就代表二位数组第一个子数组的第一个元素的地址,所以 *p 就能访问到二位数组第一个子数组的第一个元素的地址,即为 arr[0][0] ,所以运行结果是2。

例二

下面的程序在32位平台运行的结果是什么:

#include <stdio.h>int main()
{int arr[5][5];int(*p)[4];p = (int(*)[4])arr;printf("%p\n%d\n", &p[4][2] - &arr[4][2], &p[4][2] - &arr[4][2]);return 0;
}

运行结果:

下面我们来详细分析:

我们知道对于二维数组在内存中的存储依旧是连续的,就像一维数组那样,所以这里我们将其简化为这样(这里一个格子代表一个整型数据):

中间的空格为了方便看出每一个子数组。

在这一步:

int(*p)[4];
p = (int(*)[4])arr;

对于 p 是一个数组指针,类型是 int(*)[4] 然后对于 arr 就是二维数组首个子数组的地址,其类型是 int(*)[5] ,然后被强制转换为了 int(*)[4] 类型,然后赋给了 p ,假设这里的 p 中的数值是0x00ff1200:

但是由于 p 的类型是 int(*)[4] ,所以 p 一次是访问四个整型,对于 &p[4][2] 就相当于 &*(*(p + 4) + 2) ,前面的&与*可以相互抵消,所以还可以表示为 (*(p + 4) + 2) ,具体在图中就是:

然后对于 &arr[4][2] 就是二维数组第五行第三列的元素的地址,在途中就是这样:

我们可以看到这两个指针之间相差了四个整型数据,对于指针减指针,会返回指针之间的元素个数,较大的指针减较小的指针,会返回正数,反之,就返回负数,所以这里会返回-4。

这就可以解释第二个打印结果。

然而第一个结果为什么是0xFFFFFFFC呢?

这是因为%p是打印指针形式的数据,由于指针形式的数据都是非负的,就是打印十六进制非负数,而这里的-4又是负数,所以这里就被转换为正数了:

所以第一个打印结果是FFFFFFFC。

二、指针数组与指针

例一

下面的程序运行结果是什么:

#include <stdio.h>int main()
{const char* str[] = { "hello","world","abc" };const char** p = str;p++;printf("%s\n", *p);return 0;
}

运行结果:

对于str数组是字符指针数组,只不过这里的这里的字符指针是指向只读段的字符串的指针,然后及将数组的首元素地址付给 p ,然后 p 自增一,对于某种指针自增一,就会跳过这个指针指向的数据类型的大小,所以这里会跳过一个指针的大小,所以是指向数组第二个元素的指针,所以*p就是访问数组的第二个元素,第二个元素是指向 “world” 字符串的第一个字符 'w' 的指针,所以会打印 world 。

例二

下面的代码运行结果是什么:

#include <stdio.h>int main()
{const char* ps[] = { "hello","fgh","abcde","world"};const char** pps[] = { ps + 3,ps + 2,ps + 1,ps };const char*** ppps = pps;printf("%s\n", **++ppps );//abcdeprintf("%s\n", *-- * ++ppps + 3);//loprintf("%s\n", *ppps[-2] +  3);//ldprintf("%s\n", ppps[-1][-1] + 1); //ghreturn 0;
}

运行结果:

下面我们来具体分析:

具体的对应情况(这里的一个格子代表一个指针元素):

首先是第一句:

printf("%s\n", **++ppps );//abcde

++的优先级是大于*的,所以 ppps 先加加,最开始 ppps 指向 pps 的首元素,即 ppps 中是 pps 的首元素地址,然后加加后,就指向了 pps 的第二个元素,然后解引用就是 pps 的第二个元素 ps + 2,然后 ps + 2 就是 ps 的第三个元素的地址,所以 ps + 2 指向 ps 的第三个元素,然后解引用,就是 ps 的第三个元素,ps 的第三个元素是指向 "abcde" 这个字符串的第一个字符 'a' 的指针,所以会打印 abcde 这个字符串。

然后第二句:

printf("%s\n", *-- * ++ppps + 3);//lo

在上一句时因为加加,ppps 已经变成指向 pps 第二个元素的指针了,

然后这一句又有++,所以 ppps 指向的位置又向后面一了一个元素,所以这时 ppps 就指向 pps 的第三个元素了,

然后解引用,就访问到了 pps[2] ,然后就得到了 ps + 1 ,然后--,就变成了 ps ,这里的 pps[2] 中的 ps + 1 也变成了 ps ,

 ps 是数组 ps 的首元素的地址,所以 ps 指向数组 ps 的第一个元素,然后解引用,得到数组 ps 的第一个元素,即 ps[0] ,ps 的第一个元素是指向字符串 "hello" 的指针,然后因为 + 加操作符优先级在这里是最低的,所以最后进行,这时是 "hello" 字符串中第一个字符 'h' 的指针,然后进行加三操作,实际上会跳过三个字符,下图中每个格子代表一个字符数据:

这时指针指向 "hello" 中的第二个 'l' ,所以这里会打印 lo 。

然后第三句:

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

对于 ppps ,其在第二句完成后,就指向了 pps 的第三个元素了,我们知道 ppps[-2] 就相当于 *(ppps - 2) ,但这个操作不会使 ppps 指向的内容发生改变,因为没有对 ppps 造成改动,所以进行这个操作后,就得到了 pps 的第一个元素 ps + 3,ps + 3 指向数组 ps 的第四个元素,然后再解引用,就得到了 ps 的第四个元素,也就是 ps[3] ,ps[3] 是一个字符指针,指向字符串 "world" 第一个字符 'w' 的指针,然后对其进行加三操作,就会得到指向 "world" 的第四个字符 'l' 的指针,

所以会打印 ld 。

最后第四句:

printf("%s\n", ppps[-1][-1] + 1); //gh

第三句中没有改变 ppps 指向的内容,所以 ppps 还是指向 pps 的第三个元素,然后进行 ppps[-1][-1] 操作,这个操作就相当于 *(*(ppps - 1) - 1) ,里面的 *(ppps - 1) 的进行后就得到了 pps 的第二个元素了,即 pps[1] ,就是 ps + 2 ,然后外层减一,就变成了 ps + 1 ,ps + 1 指向数组 ps 的第二个元素,解引用后就得到了数组 ps 的第二个元素了,即 ps[1] ,而ps[1] 是一个指向字符串 "fgh" 第一个字符 'f' 的指针,然后进行加一操作,就指向了 "fgh" 的第二个字符 'g' ,

所以会打印 gh 。

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

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

相关文章

教师编制可以跨市调动吗

在教育的广阔天地中&#xff0c;我们常常面临各种职业发展的选择。作为一名教师&#xff0c;是否能够实现跨市调动&#xff0c;这不仅是一个职业发展的问题&#xff0c;更关系到个人生活和职业规划的诸多方面。今天&#xff0c;我们就来探讨一下&#xff0c;拥有编制身份的教师…

电磁兼容(EMC):静电放电(ESD)抗扰度试验深度解读(五)

静电放电过程是一个很复杂的过程&#xff0c;下面比对人体持金属对产品放电和静电发生器对产品进行接触放电过程的详细分解说明。 1. 人持金属对产品放电过程 人对产品所产生的静电放电&#xff0c;会发生下面一系列的事件&#xff1a; 1&#xff09;当手持金属片接近产品的…

算法题解记录20+++

题目描述&#xff1a; 难度&#xff1a;简单 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来…

华为路由器基于接口限速

一、背景 ISP与企业内网通过华为路由器接入Internet时,当大量流量进入路由器时,可能会因为带宽不足产生拥塞,导致丢包,严重影响用户上网体验。对于此需要对网络流量进行限制,其方式通常有防火墙带宽策略、路由器基于接口限速等。 二、华为路由器基于接口限速方式 在路由…

【看不懂命令行、.yaml?】Hydra 库极速入门

Hydra 是一个开源的 Python 框架&#xff0c;可以简化研究和其他复杂应用程序的开发。其核心功能是通过组合动态创建层次化的配置&#xff0c;并可以通过配置文件和命令行进行覆盖。Hydra 的名字来源于它能够运行多个类似的作业 - 就像一个多头的水怪一样。 主要特性: 从多个…

T31开发笔记: 移动侦测

若该文为原创文章&#xff0c;转载请注明原文出处。 最近在测试创安源IPC时发现摄像头的视频流有移动侦测功能 &#xff0c;拆解后发现使用的是T31,刚好手头上有淘宝买50多点的T31摄像头&#xff0c;就自己现在了个简易DEMO测试一下。 一、硬件和开发环境 1、硬件&#xff1a;…

C语言 分支控制语句之 if

然后 我们来说 流程控制语句之 if 选择控制结构 是通过 分支语句来实现的 其中 包括 单分支选择语句通过 (if) 来实现 双分支语句通过 (if) 和 (else) 实现 多分支语句通过 (if) (else if) (else) 实现 对于单分支来讲 它控制的语句就是 要嘛做 要嘛不做 好比如 放假了 你是…

【极速前进】20240422:预训练RHO-1、合成数据CodecLM、网页到HTML数据集、MLLM消融实验MM1、Branch-Train-Mix

一、RHO-1&#xff1a;不是所有的token都是必须的 论文地址&#xff1a;https://arxiv.org/pdf/2404.07965.pdf 1. 不是所有token均相等&#xff1a;token损失值的训练动态。 ​ 使用来自OpenWebMath的15B token来持续预训练Tinyllama-1B&#xff0c;每1B token保存一个che…

夜鸦国际服账号验证怎么办 夜鸦国际服账号认证的详细教程

夜鸦国际服账号验证怎么办 夜鸦国际服账号认证的详细教程 今天为大家带来的是《夜鸦》这款游戏&#xff0c;游戏背景是基于13世纪欧洲背景的MMORPG游戏&#xff0c;这款游戏以其沉浸式的游戏体验和流畅的打斗为特色。玩家可以选择战士、剑士、猎人或女巫等角色&#xff0c;体验…

AQS(AbstractQueuedSynchronizer)队列同步器源码解读

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 1. 前言 2. AOS、AQS、AQLS的区别 3. AQS的底层原理 3.1. 核心思想 3.2. 数…

李廉洋:4.23黄金休市之后大幅下跌,原油小幅度上涨。走势分析!

今年以来推动金价上涨的因素是亚洲的需求&#xff0c;很可能来自各国央行。最近又有零售买盘和一些金融买盘作为补充。目前的问题是&#xff0c;不断上升的债券收益率正在争夺资金。美国2年期国债的收益率接近5%&#xff0c;在美联储降息导致收益率开始下降之前&#xff0c;这仍…

JavaScript权威指南(第7版) 笔记 - 第 7 章 数组

能用代码说清楚的&#xff0c;绝不多废话&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; Linux创始人Linus的名言&#xff1a;Talk is cheap&#xff0c;show me the code ! &#xff0c;博主技术博文会精心给出能说明问题的范例代码&#xff01;…

Qt实现XYModem协议(五)

1 概述 XMODEM协议是一种使用拨号调制解调器的个人计算机通信中广泛使用的异步文件运输协议。这种协议以128字节块的形式传输数据&#xff0c;并且每个块都使用一个校验和过程来进行错误检测。使用循环冗余校验的与XMODEM相应的一种协议称为XMODEM-CRC。还有一种是XMODEM-1K&am…

35K的鸿蒙音视频开发岗位面经分享~

一个月前&#xff0c;阿里云在官网音视频终端 SDK 栏目发布适配 HarmonyOS NEXT 的操作文档和 SDK&#xff0c;官宣 MediaBox 音视频终端 SDK 全面适配 HarmonyOS NEXT。 此外&#xff0c;阿里云播放器 SDK 也在华为开发者联盟官网鸿蒙生态伙伴 SDK 专区同步上线&#xff0c;面…

面向对象设计与分析40讲(25)中介模式、代理模式、门面模式、桥接模式、适配器模式

文章目录 门面模式代理模式中介模式 之所以把这几个模式放到一起写&#xff0c;是因为它们的界限比较模糊&#xff0c;结构上没有明显的差别&#xff0c;差别只是语义上。 这几种模式在结构上都类似&#xff1a; 代理将原本A–>C的直接调用变成&#xff1a; A–>B–>…

负采样重要吗?它的理论与应用综述

Does Negative Sampling Matter? A Review with Insights into its Theory and Applications 负采样重要吗&#xff1f;它的理论与应用综述 Does Negative Sampling Matter? A Review with Insights into its Theory and Applications Zhen Yang, Ming Ding, Tinglin Huang,…

基于python实现web漏洞挖掘技术的研究(django)

基于python实现web漏洞挖掘技术的研究(django) 开发语言:Python 数据库&#xff1a;MySQL所用到的知识&#xff1a;网络爬虫&#xff0c;SQL注入&#xff0c;XSS漏洞工具&#xff1a;pycharm、Navicat、Maven 系统的实现与漏洞挖掘 系统的首页面 此次的系统首页面是登录的页…

BootstrapAdmin Net7:基于RBAC的后台管理框架,实现精细化权限管理与多站点单点登录

BootstrapAdmin Net7&#xff1a;基于RBAC的后台管理框架,实现精细化权限管理与多站点单点登录 摘要 随着企业信息化建设的不断深入&#xff0c;后台管理系统在企业运营中扮演着越来越重要的角色。本文介绍了一款基于RBAC&#xff08;Role-Based Access Control&#xff09;的…

291个地级市资源错配指数、劳动和资本相对扭曲指数(2006-2021年)

01、数据介绍 资源错配指数&#xff08;Misallocation Index&#xff09;是一个用于衡量资源配置效率的指标&#xff0c;它衡量的是生产要素的配置是否合理&#xff0c;是否达到了最优的状态。资源错配指数越高&#xff0c;资源的利用效率越低。资源错配指数主要用于衡量各种生…

企业实施定制鞋厂ERP软件需要注意哪些问题?

企业实施定制鞋厂ERP软件是个复杂的管理系统工程&#xff0c;为了成功地为企业定制实施ERP软件&#xff0c;需要注意和解决几个关键的问题&#xff1a; . 确立ERP系统实施和定制的决策者&#xff1b;. 做好前期咨询与调研工作&#xff1b;. 做好系统产品或项目迭代规划&#x…