【C语言】数 组与指针:深度剖析与等价表达


在这里插入图片描述

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳]
本文专栏: C语言

文章目录

  • 💯前言
  • 💯数组与指针的基本关系
  • 💯数组与指针的互换使用
    • 数组下标与指针的等价性
  • 💯六个表达式的等价性
  • 💯指针运算的注意事项
  • 💯数组与指针的转换实例
    • 分析和解释 C 语言代码:数组与指针的运算
    • 1. 定义数组和指针
    • 2. 输入 10 个整数
    • 3. 使用不同的方式输出数组元素
      • 3.1 使用 `arr[i]` 输出数组元素
      • 3.2 使用 `*(arr + i)` 输出数组元素
      • 3.3 使用 `*(i + arr)` 输出数组元素
      • 3.4 使用 `i[p]` 输出数组元素
      • 3.5 使用 `p[i]` 输出数组元素
      • 3.6 使用 `*(p + i)` 输出数组元素
    • 4. 输出示例
    • 总结
  • 💯小结

在这里插入图片描述


在这里插入图片描述


💯前言

  • 在 C 语言中,数组和指针是两个基础但至关重要的概念。它们之间有着复杂且紧密的关系,理解数组和指针的使用方法、它们如何互相转换,能够帮助程序员写出更加高效和简洁的代码。尤其是当我们在使用数组时,如果能够熟练地运用指针的方式来访问数组元素,不仅能够提升代码的执行效率,还能够加深对 C 语言内存模型的理解。
    本篇文章将详细探讨数组和指针的关系,特别是它们的互换性以及一些常见的等价表达。文章中的分析将基于以下几个方面:数组的定义与特性,指针的作用,数组与指针的互换使用,以及一些常见的数组访问方式。通过这些内容,我们将深入了解 C 语言中数组和指针的妙用。
    C语言
    在这里插入图片描述

💯数组与指针的基本关系

  1. 数组的本质:

    在 C 语言中,数组是同类型数据的集合,它在内存中占用一块连续的空间。数组的大小是固定的,并且数组的元素是按顺序存储的。数组的首元素的地址就是数组名,数组名相当于一个指针,指向数组的第一个元素。

    数组的定义:

    int arr[5];
    

    这段代码定义了一个包含5个整数的数组。数组 arr 在内存中占用的是一块连续的空间,数组名 arr 实际上代表了数组首元素的地址。

  2. 指针与数组:

    指针是一个存储内存地址的变量。指针本身可以指向任何类型的数据,比如指向整数、字符、结构体等。当我们定义一个指针时,指针变量需要存储一个地址,并且这个地址必须指向相应类型的数据。

    指针的定义:

    int* p;
    p = arr;
    

    这里,指针 p 指向了数组 arr 的首元素。此时,指针 p 和数组 arr 有着密切的关系,它们指向的内存地址是相同的。


💯数组与指针的互换使用

在 C 语言中,数组和指针是可以互换使用的。这是由于数组名代表的是指向数组首元素的指针。事实上,数组名和指针的关系让我们可以使用指针访问数组中的元素。具体来说,数组下标运算符([])和指针运算符(*)有着紧密的联系。

数组下标与指针的等价性

通过指针可以访问数组的元素,这是 C 语言中的一个重要特性。实际上,数组下标运算符和指针运算符在本质上是等价的,下面是几种等价的表达方式:

  1. arr[i]*(arr + i)

    • arr[i] 是数组下标的常见形式,访问数组中第 i 个元素。
    • *(arr + i) 是通过指针运算的方式访问数组中第 i 个元素。这里,arr 是数组名,表示数组首元素的地址,arr + i 就是数组首元素地址偏移 i 个位置,* 用于解引用得到相应的值。
  2. *(arr + i)*(i + arr)

    • 这两个表达式是等价的,因为加法运算是交换律的。arr + ii + arr 都指向数组中第 i 个元素。通过 * 运算符解引用后,它们的结果相同。
  3. arr[i]i[arr]

    • 虽然 i[arr] 看起来不太直观,但它与 arr[i] 是完全等价的。C 语言中的数组访问本质上是通过指针加偏移量来完成的,因此 arr[i] 实际上是 *(arr + i),而 i[arr]*(i + arr),它们的运算结果是一样的。

💯六个表达式的等价性

在 C 语言中,数组和指针的关系使得某些看起来不同的写法,实际上是完全等价的。以下是六个等价的表达式:

  1. arr[i]*(arr + i)

    • arr[i] 是常见的数组下标访问方式,而 *(arr + i) 则是通过指针访问第 i 个元素。两者等价。
  2. *(arr + i)*(i + arr)

    • 由于加法的交换律,*(arr + i)*(i + arr) 也是等价的,指向的是同一元素。
  3. arr[i]i[arr]

    • arr[i]i[arr] 是等价的表达方式,虽然后者不常见,但在 C 语言中合法且结果相同。
  4. *(arr + i)p[i]

    • p[i] 是指针访问数组的常见形式,等同于 *(p + i),通过偏移量访问数组中的元素。
  5. *(arr + i)*(p + i)

    • *(arr + i)*(p + i) 之间的关系类似,都是通过指针加偏移量来访问数组元素。
  6. *(i + arr)i[arr]

    • 这两种表达式本质上相同,*(i + arr)i[arr] 指向的是相同的内存位置,因而是等价的。

💯指针运算的注意事项

尽管 i[arr] 是合法的且等价于 arr[i],但是这种写法通常不推荐使用,因为它不直观,可能让代码的阅读者产生困惑。通常我们更倾向于使用 arr[i]p[i] 这样的常见形式,这样代码更加清晰易懂。


💯数组与指针的转换实例

我们来分析一个简单的程序,演示如何使用指针访问数组。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdio.h>int main() {int arr[10] = { 0 };  // 定义一个大小为 10 的整数数组int* p = arr;       // 定义指针 p,指向数组 arrint sz = sizeof(arr) / sizeof(arr[0]); // 计算数组元素个数int i = 0;// 输入 10 个整数for (i = 0; i < sz; i++) {scanf("%d", p + i);  // 使用指针来访问数组}printf("使用arr[i]:");// 输出 10 个整数for (i = 0; i < sz; i++) {printf("%d ", arr[i]);  // 使用指针访问数组并输出}printf("\n");printf("使用*(arr + i):");// 输出 10 个整数for (i = 0; i < sz; i++) {printf("%d ", *(arr + i));  // 使用指针访问数组并输出}printf("\n");printf("使用*(i + arr):");// 输出 10 个整数for (i = 0; i < sz; i++) {printf("%d ", *(i + arr));  // 使用指针访问数组并输出}printf("\n");printf("使用arr[i]:");// 输出 10 个整数for (i = 0; i < sz; i++) {printf("%d ", arr[i]);  // 使用指针访问数组并输出}printf("\n");printf("使用i[p]:");// 输出 10 个整数for (i = 0; i < sz; i++) {printf("%d ", i[p]);  // 使用指针访问数组并输出}printf("\n");printf("使用p[i]:");// 输出 10 个整数for (i = 0; i < sz; i++) {printf("%d ", p[i]);  // 使用指针访问数组并输出}printf("\n");printf("使用*(p + i):");// 输出 10 个整数for (i = 0; i < sz; i++) {printf("%d ", *(p + i));  // 使用指针访问数组并输出}return 0;
}

在这里插入图片描述

分析和解释 C 语言代码:数组与指针的运算

这段代码展示了如何在 C 语言中使用数组和指针的不同方式来访问和输出数组的元素。通过指针运算,可以以多种形式访问和输出数组的内容。让我们逐步分析这段代码。

1. 定义数组和指针

int arr[10] = { 0 };  // 定义一个大小为 10 的整数数组
int* p = arr;         // 定义指针 p,指向数组 arr
int sz = sizeof(arr) / sizeof(arr[0]); // 计算数组元素个数
  • arr 是一个大小为 10 的整型数组,初始化为 0
  • p 是一个指针,指向 arr 数组的首元素。
  • sz 是数组 arr 的大小,通过 sizeof(arr) / sizeof(arr[0]) 来计算数组的元素个数。这里 sizeof(arr) 获取数组总大小,sizeof(arr[0]) 获取数组单个元素的大小,因此 sz 即为数组中元素的个数。

2. 输入 10 个整数

for (i = 0; i < sz; i++) {scanf("%d", p + i);  // 使用指针来访问数组
}
  • 使用 scanf 输入 10 个整数,并将它们存入数组 arr 中。这里通过 p + i 来操作数组,因为 p 是指向数组首元素的指针,p + i 相当于指向数组第 i 个元素的指针,scanf 会把输入的整数存入该位置。

3. 使用不同的方式输出数组元素

接下来的代码展示了如何用不同的方式输出数组的元素:

3.1 使用 arr[i] 输出数组元素

printf("使用arr[i]:");
for (i = 0; i < sz; i++) {printf("%d ", arr[i]);  // 直接使用数组下标访问数组元素并输出
}
  • 通过 arr[i] 直接访问数组元素并输出。这是最常见的访问数组元素的方式。

3.2 使用 *(arr + i) 输出数组元素

printf("使用*(arr + i):");
for (i = 0; i < sz; i++) {printf("%d ", *(arr + i));  // 使用指针运算来访问数组元素并输出
}
  • *(arr + i) 是通过指针加偏移量来访问数组元素。arr 是数组首元素的地址,arr + i 就是数组第 i 个元素的地址,* 用来解引用,得到该地址存储的值。

3.3 使用 *(i + arr) 输出数组元素

printf("使用*(i + arr):");
for (i = 0; i < sz; i++) {printf("%d ", *(i + arr));  // 使用指针运算来访问数组元素并输出
}
  • *(i + arr)*(arr + i) 完全等价,它们的运算方式是一样的。这里也展示了指针偏移量的交换性。

3.4 使用 i[p] 输出数组元素

printf("使用i[p]:");
for (i = 0; i < sz; i++) {printf("%d ", i[p]);  // 通过指针加偏移量来访问数组元素并输出
}
  • i[p] 是合法且等价于 p[i] 的写法。它看起来不太直观,但本质上是通过指针偏移量访问数组元素。实际上,i[p] 是等同于 *(i + p),和 *(p + i) 相同。

3.5 使用 p[i] 输出数组元素

printf("使用p[i]:");
for (i = 0; i < sz; i++) {printf("%d ", p[i]);  // 使用指针访问数组并输出
}
  • p[i] 是通过指针访问数组元素的常见方式,等同于 *(p + i)

3.6 使用 *(p + i) 输出数组元素

printf("使用*(p + i):");
for (i = 0; i < sz; i++) {printf("%d ", *(p + i));  // 使用指针运算来访问数组元素并输出
}
  • *(p + i) 是通过指针偏移量访问数组元素。p 是指向数组首元素的指针,p + i 就是数组第 i 个元素的指针,* 解引用该指针并输出元素值。

4. 输出示例

假设你输入了以下数据:

1 2 3 4 5 6 7 8 9 10

输出结果将是:

使用arr[i]:1 2 3 4 5 6 7 8 9 10
使用*(arr + i):1 2 3 4 5 6 7 8 9 10
使用*(i + arr):1 2 3 4 5 6 7 8 9 10
使用arr[i]:1 2 3 4 5 6 7 8 9 10
使用i[p]:1 2 3 4 5 6 7 8 9 10
使用p[i]:1 2 3 4 5 6 7 8 9 10
使用*(p + i):1 2 3 4 5 6 7 8 9 10

总结

这段代码展示了数组和指针之间的密切关系。通过不同的指针访问方式,如 arr[i]*(arr + i)*(i + arr)i[p]p[i],我们可以看到这些方式实际上是等价的,它们都可以用来访问数组中的元素。通过指针的运算,可以非常灵活地操作数组元素。


💯小结

本文详细分析了 C 语言中的数组与指针,特别是它们之间的等价表达方式。我们发现,数组下标运算符和指针运算符在很多情况下是等价的,指针的使用不仅可以访问数组,还能使得程序更加灵活与高效。通过理解数组名、指针和下标之间的关系,程序员可以在编写代码时更加得心应手。

对于数组和指针的相关表达式,尽管它们在语法上可能有不同的形式,但它们在底层的运作原理是相同的。掌握这些等价的表达方式,将有助于你在 C 语言编程中更加灵活地运用数组与指针。

通过本篇文章的讲解,希望读者能够对数组和指针之间的关系有更深刻的理解,并能够在实践中熟练地使用这些技巧,以提高代码的效率和可读性。


在这里插入图片描述


在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

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

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

相关文章

寒假2.7

题解 web&#xff1a;[HCTF 2018]WarmUp 打开是张表情包 看一下源代码 访问source.php&#xff0c;得到完整代码 代码审计 <?phphighlight_file(__FILE__);class emmm{public static function checkFile(&$page){$whitelist ["source">"source.p…

sqli-lab靶场学习(五)——Less15-17(post方法盲注、修改密码)

前言 第11-14关开始用post方法&#xff0c;15-17关会用到盲注&#xff0c;post方法盲注和get方法类似。 Less15 这关是单引号闭合&#xff0c;有报错但没有具体情况的回显&#xff0c;因此适合使用错误盲注。 在用户名密码框分别输入 账号&#xff1a;admin and 11 -- asd…

【Spring】什么是Spring?

什么是Spring&#xff1f; Spring是一个开源的轻量级框架&#xff0c;是为了简化企业级开发而设计的。我们通常讲的Spring一般指的是Spring Framework。Spring的核心是控制反转(IoC-Inversion of Control)和面向切面编程(AOP-Aspect-Oriented Programming)。这些功能使得开发者…

VSCode便捷开发

一、常用插件 Vue 3 Snippets、Vetur、Vue - Official 二、常用开发者工具 三、Vue中使用Element-UI 安装步骤&#xff1a; 1、在VSCode的终端执行如下指令&#xff1a; npm i element-ui -S 2、在main.js中全局引入&#xff1a; import Vue from vue; import ElementUI from …

Android studio 创建aar包给Unity使用

1、aar 是什么&#xff1f; 和 Jar有什么区别 aar 和 jar包 都是压缩包&#xff0c;可以使用压缩软件打开 jar包 用于封装 Java 类及其相关资源 aar 文件是专门为 Android 平台设计的 &#xff0c;可以包含Android的专有内容&#xff0c;比如AndroidManifest.xml 文件 &#…

加速汽车软件升级——堆栈刷写技术的应用与挑战

一、背景和挑战 | 背景&#xff1a; 当前汽车市场竞争激烈&#xff0c;多品牌并存&#xff0c;新车发布速度加快&#xff0c;价格逐渐降低&#xff0c;功能日益多样化。随着车辆功能的不断提升与优化&#xff0c;ECU&#xff08;电子控制单元&#xff09;的代码量也随之增加&…

台湾精锐APEX减速机在半导体制造设备中的应用案例

半导体制造设备对传动系统的精度、可靠性和稳定性要求极高&#xff0c;台湾精锐APEX减速机凭借其低背隙、高精度和高刚性等优势&#xff0c;在半导体制造设备中得到了广泛应用。 案例一&#xff1a;晶圆切割设备 1.应用场景 在晶圆切割过程中&#xff0c;设备需要高精度的运…

Windows安装cwgo,一直安装的是linux平台的

Windows安装cwgo&#xff0c;一直安装的是linux平台的 查看 go env &#xff0c;发现 GOOSlinux 临时修改 GOOS &#xff0c;set GOOSwindows &#xff0c;再安装。 此时&#xff0c;安装的就是 windows 的可执行文件。安装之后再将 GOOS 修改回来即可。

【R语言】plyr包和dplyr包

一、plyr包 plyr扩展包主要是实现数据处理中的“分割-应用-组合”&#xff08;split-apply-combine&#xff09;策略。此策略是指将一个问题分割成更容易操作的部分&#xff0c;再对每一部分进行独立的操作&#xff0c;最后将各部分的操作结果组合起来。 plyr扩展包中的主要函…

google 多模态aistudio Stream Realtime体验

参考&#xff1a; https://aistudio.google.com/live 使用gemini多模态能力&#xff0c;支持语音图像文字输入输出&#xff0c;实时交互体验 支持语音实时交互、摄像头加语音、屏幕视频语音 摄像头 屏幕共享

opentelemetry-collector 配置elasticsearch

一、修改otelcol-config.yaml receivers:otlp:protocols:grpc:endpoint: 0.0.0.0:4317http:endpoint: 0.0.0.0:4318 exporters:debug:verbosity: detailedotlp/jaeger: # Jaeger supports OTLP directlyendpoint: 192.168.31.161:4317tls:insecure: trueotlphttp/prometheus: …

四、OSG学习笔记-基础图元

前一章节&#xff1a; 三、OSG学习笔记-应用基础-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/145514021 代码&#xff1a;CuiQingCheng/OsgStudy - Gitee.com 一、绘制盒子模型 下面一个简单的 demo #include<windows.h> #include<osg/Node&…

保姆级AI开发环境搭建

目录 windows下环境搭建1. Python环境搭建2. 下载vLLM2.1 安装CUDA2.2 安装Pytorch2.3 安装vllm 3. 部署Deepseek&#xff08;huggingface&#xff09;3.1 DeepSeek的优化建议 4. ollama快速部署Deepseek4.1 下载Ollama4.2 配置Ollma4.2 运行模型4.3 其他Ollama命令 linux下环境…

MySQL安装与配置

MySQL是常用的数据库&#xff0c;本篇记录MySQL的安装与配置。 1.首先到官网下载MySQL&#xff0c;这里下载5.7版本的。 https://downloads.mysql.com/archives/community/ 2.下载完成后&#xff0c;解压&#xff0c;然后设置环境变量 3.打开解压的要目录&#xff0c;创建一个…

如何参与开源项目

目的 就是说一下如何参与开源的项目&#xff0c;通过参与QXlsx来说明开源项目是如何参与的&#xff0c;其它的github上的开源项目&#xff0c;也是这样的流程。 关于GitHub: GitHub是一个面向开源及私有软件项目的托管平台&#xff0c;因为只支持Git作为唯一的版本库格式进行…

edu小程序挖掘严重支付逻辑漏洞

edu小程序挖掘严重支付逻辑漏洞 一、敏感信息泄露 打开购电小程序 这里需要输入姓名和学号&#xff0c;直接搜索引擎搜索即可得到&#xff0c;这就不用多说了&#xff0c;但是这里的手机号可以任意输入&#xff0c;只要用户没有绑定手机号这里我们输入自己的手机号抓包直接进…

【论文翻译】DeepSeek-V3论文翻译——DeepSeek-V3 Technical Report——第一部分:引言与模型架构

论文原文链接&#xff1a;DeepSeek-V3/DeepSeek_V3.pdf at main deepseek-ai/DeepSeek-V3 GitHub 特别声明&#xff0c;本文不做任何商业用途&#xff0c;仅作为个人学习相关论文的翻译记录。本文对原文内容直译&#xff0c;一切以论文原文内容为准&#xff0c;对原文作者表示…

Qt之设置QToolBar上的按钮样式

通常给QAction设置icon后,菜单栏的菜单项和工具栏(QToolBar)上对应的按钮会同时显示该icon。工具栏还可以使用setToolButtonStyle函数设置按钮样式,其参数为枚举值: enum ToolButtonStyle {ToolButtonIconOnly,ToolButtonTextOnly,ToolButtonTextBesideIcon,ToolButtonTe…

学习threejs,使用Lensflare模拟镜头眩光

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.Lensflare 二、&…

opencv图像处理

注释详细 1.图像维度&#xff1a;打印出的结果分别为图片像素的横行、纵列和三原色彩色通道 import cv2 imgcv2.imread(pictures//3.png) print(img.shape) cv2.imshow("img",img)#窗口名、变量名 cv2.waitKey(0) 2.图像彩色通道&#xff1a;1张彩色图片&#xff…