当前位置: 首页 > news >正文

C语言中的数组并非指针:深入理解数组和指针的区别

前言

在C语言中,数组和指针是两个非常重要的概念,它们在很多方面有着紧密的联系,但也存在显著的区别。尽管数组名有时可以像指针那样使用,但它们本质上并不是一回事。理解这些差异对于编写正确和高效的代码至关重要。本文将深入探讨数组和指针的区别,并提供一些示例代码。

381950c3d9a44c27b10d2fc1c418af1a.jpeg

1. 数组与指针的基础概念

  • 数组:数组是一系列相同类型数据的集合,它们在内存中连续存储。数组名本身是一个常量,指向数组的起始位置。
  • 指针:指针是一个变量,其值为另一个变量的地址。指针可以指向数组中的任何一个元素。

2. 数组与指针的相似之处

尽管数组和指针有很多不同之处,但它们在某些方面确实很相似:

  • 数组名作为指针:在许多上下文中,数组名可以被用作指向数组第一个元素的指针。
  • 指针算术:指针可以进行算术运算,如 ptr + 1,这同样适用于数组名。

3. 数组与指针的主要区别

现在让我们来看看数组和指针之间的一些关键区别:

3.1 数组名是常量

数组名始终指向数组的起始位置,不能被重新赋值为指向其他位置的地址。

1#include <stdio.h>
2
3int main() {
4    int arr[5] = {1, 2, 3, 4, 5};
5    int *ptr = arr; // arr 被视为指向第一个元素的指针
6
7    printf("Value at arr: %d\n", *arr); // 输出 1
8    printf("Value at ptr: %d\n", *ptr); // 输出 1
9
10    // 下面的代码会导致编译错误
11    // arr = ptr; // 错误:数组名不能被重新赋值
12
13    return 0;
14}

输出:

Value at arr: 1
Value at ptr: 1

解释

  • int *ptr = arr; 将 arr 视为指向第一个元素的指针。
  • arr = ptr; 导致编译错误,因为数组名不能被重新赋值。

3.2 数组名与指针的类型不同

数组名的类型与指针的类型不同,这在函数参数传递时尤为明显。

1#include <stdio.h>
2
3void printArray(int arr[], int size) {
4    for (int i = 0; i < size; i++) {
5        printf("%d ", arr[i]);
6    }
7    printf("\n");
8}
9
10int main() {
11    int arr[5] = {1, 2, 3, 4, 5};
12
13    printArray(arr, 5); // arr 被传递给函数
14
15    return 0;
16}

输出:

1 2 3 4 5

解释

  • void printArray(int arr[], int size) 接受一个数组作为参数。
  • printArray(arr, 5); 传递数组给函数。

3.3 数组作为函数参数时的退化

当数组作为函数参数时,它会退化为指针,这意味着传递给函数的是数组首元素的地址,而不是整个数组。

1#include <stdio.h>
2
3void printArray(int arr[], int size) {
4    // arr 在这里被视为指针
5    printf("Address of arr in function: %p\n", (void *)arr);
6}
7
8int main() {
9    int arr[5] = {1, 2, 3, 4, 5};
10
11    printf("Address of arr in main: %p\n", (void *)&arr);
12    printArray(arr, 5); // arr 作为指针传递给函数
13
14    return 0;
15}

输出:

1Address of arr in main: 0x7fff5fbff3e0
2Address of arr in function: 0x7fff5fbff3e0

解释

  • printArray(arr, 5); 传递数组给函数。
  • arr 在函数中被视为指向数组第一个元素的指针。

3.4 数组大小的信息丢失

当数组作为函数参数时,编译器不知道数组的实际大小。这可能导致潜在的问题,如越界访问。

1#include <stdio.h>
2
3void printArray(int arr[], int size) {
4    for (int i = 0; i < size; i++) {
5        printf("%d ", arr[i]);
6    }
7    printf("\n");
8}
9
10int main() {
11    int arr[5] = {1, 2, 3, 4, 5};
12
13    printArray(arr, 5); // 正确
14    printArray(arr, 10); // 可能导致越界访问
15
16    return 0;
17}

输出:

11 2 3 4 5

解释

  • printArray(arr, 10); 可能导致越界访问。

4. 数组与指针的高级用法

数组和指针在高级编程中有着广泛的应用,例如多维数组、指针数组等。

4.1 多维数组与指针

多维数组可以被视为指针数组。

1#include <stdio.h>
2
3void printMatrix(int (*matrix)[3], int rows) {
4    for (int i = 0; i < rows; i++) {
5        for (int j = 0; j < 3; j++) {
6            printf("%d ", matrix[i][j]);
7        }
8        printf("\n");
9    }
10}
11
12int main() {
13    int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
14
15    printMatrix(matrix, 2); // 传递多维数组给函数
16
17    return 0;
18}

输出:

1 2 3 
4 5 6 

解释

  • void printMatrix(int (*matrix)[3], int rows) 接受一个指针数组作为参数。
  • printMatrix(matrix, 2); 传递多维数组给函数。

结论

数组和指针在C语言中有着密切的关系,但它们之间也存在着明显的区别。理解这些差异对于编写正确和高效的代码至关重要。通过上述示例,你应该已经了解了数组和指针之间的主要区别。这种能力对于处理复杂的数据结构和编写更高效的程序非常有帮助。

 

相关文章:

C语言中的数组并非指针:深入理解数组和指针的区别

前言 在C语言中&#xff0c;数组和指针是两个非常重要的概念&#xff0c;它们在很多方面有着紧密的联系&#xff0c;但也存在显著的区别。尽管数组名有时可以像指针那样使用&#xff0c;但它们本质上并不是一回事。理解这些差异对于编写正确和高效的代码至关重要。本文将深入探…...

Topaz Video AI for Mac 视频无损放大软件安装教程【保姆级,操作简单轻松上手】

Mac分享吧 文章目录 Topaz Video AI for Mac 视频无损放大软件 安装完成&#xff0c;软件打开效果一、Topaz Video AI 视频无损放大软件 Mac电脑版——v5.3.5⚠️注意事项&#xff1a;1️⃣&#xff1a;下载软件2️⃣&#xff1a;安装软件&#xff0c;将安装包从左侧拖入右侧文…...

虚函数和纯虚函数是 C++ 中实现多态性的关键概念

虚函数&#xff08;Virtual Function&#xff09; 定义&#xff1a;虚函数是在基类中使用 virtual 关键字声明的函数&#xff0c;目的是允许派生类重写该函数。用途&#xff1a;通过虚函数&#xff0c;基类指针或引用可以调用派生类中重写的函数&#xff0c;从而实现动态多态性…...

计算机网络IP地址分类,子网掩码,子网划分复习资料

IP 地址的概念 IP 地址是独立于硬件地址的逻辑地址&#xff0c;它是由软件提供的地址。 IP 地址是网络层地址。 IP 编址方案和分类 IP 地址由 32 位二进制数构成&#xff0c;分为前缀(网络地址)和后缀(主机地址) 同一网段中每台计算机的 IP 地址是唯一的网络地址的分配全球…...

LINUX下使用SQLite查看.db数据库文件

目录 1. 安装 SQLite 对于 Debian/Ubuntu 系统&#xff1a; 2.安装完成后操作 打开 SQLite 命令行工具并连接到数据库文件 查看表结构 查询表中的数据 执行其他 SQL 操作 3. 退出 SQLite 命令行工具 4. 使用图形化工具&#xff08;可选&#xff09; 总结 在 Linux 环…...

基于uniapp微信小程序的校园二手书交易系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…...

性能测试中的操作系统参数优化

目录 以下是一些针对性能测试的操作系统优化建议 关闭不必要的服务和程序&#xff1a; 更新系统和驱动程序&#xff1a; 优化电源管理设置&#xff1a; 调整内存配置&#xff1a; 网络配置优化&#xff1a; 磁盘I/O优化&#xff1a; 内核参数调整&#xff1a; 安全软件…...

rabbitmq高级特性(2)TTL、死信/延迟队列、事务与消息分发

目录 1.TTL 1.1.设置消息过期时间 1.2.设置队列过期时间 2.死信队列 2.1.介绍 2.2.演示 3.延迟队列 3.1.模拟实现延迟队列 3.2.延迟队列插件 4.事务与消息分发 4.1.事务 4.2.消息分发 1.TTL 所谓的ttl&#xff0c;就是过期时间。对于rabbitmq&#xff0c;可以设置…...

了解一下,RN中怎么加载 threejs的

在React Native&#xff08;RN&#xff09;中加载和使用Three.js&#xff0c;一个流行的3D图形库&#xff0c;通常需要一些额外的步骤&#xff0c;因为Three.js主要是为Web浏览器设计的&#xff0c;而React Native则使用原生的渲染引擎。不过&#xff0c;有一些方法可以在React…...

笔记整理—linux驱动开发部分(1)驱动梗概

驱动可以分为广义上的和狭义上的驱动。广义上的驱动是用于操作硬件的代码&#xff0c;而狭义上的驱动为基于内核系统之上让硬件去被操作的逻辑方法。 linux体系架构&#xff1a; 1.分层思想 &#xff1a;在OS中间还会有许多层。 : 2.驱动的上面是系统调用&#xff08;API&…...

金融领域中的敏感性分析和期权价值计算相关的操作

代码主要进行了金融领域中的敏感性分析和期权价值计算相关的操作。首先通过一系列方程求解S3和S2的值,然后基于这些值以及给定的参数计算一些中间变量(a1、a2、a3、b1、b2、b3),最后利用多元正态分布函数(mvncdf)和一元正态分布函数(normcdf)计算期权价值C、净现值(NP…...

GraphQL系列 - 第1讲 GraphQL语法入门

目录 一、介绍GraphQL二、GraphQL基本使用方法三、Schema 定义语言 (SDL)3.1 类型定义1&#xff09;对象类型2&#xff09;标量类型3&#xff09;枚举类型4&#xff09;输入类型5&#xff09;列表类型6&#xff09;非空类型7&#xff09;接口类型8&#xff09;联合类型 3.2 查询…...

015:地理信息系统开发平台ArcGIS Engine10.2与ArcGIS SDK for the Microsoft .NET Framework安装教程

摘要&#xff1a;本文详细介绍地理信息系统开发平台ArcGIS Engine10.2与ArcGIS SDK for the Microsoft .NET Framework的安装流程。 一、软件介绍 ArcGIS Engine 10.2是由Esri公司开发的一款强大的GIS&#xff08;地理信息系统&#xff09;开发平台。该软件基于ArcGIS 10.2 fo…...

Android——显式/隐式Intent

概述 在Android中&#xff0c;Intent是各个组件之间信息通信的桥梁&#xff0c;它用于Android各组件的通信。 Intent 的组成部分 一、显式 Intent 第一种方式 Intent intent new Intent(this, ActFinishActivity.class);startActivity(intent);第二种方式 Intent intent …...

【鸿蒙HarmonyOS实战:通过华为应用市场上架测试版App实现HBuilder X打包的UniApp项目的app转hap教程(邀请码)方式教程详解】

鸿蒙HarmonyOS实战&#xff1a;通过华为应用市场上架测试版App实现HBuilder X打包的UniApp项目的app转hap教程&#xff08;邀请码&#xff09;方式详解 在使用uniapp打包的鸿蒙项目的过程中&#xff0c;由于生成的是app文件&#xff0c;而hdc传给鸿蒙HarmonyOS系统需要的是hap文…...

一篇文章入门傅里叶变换

文章目录 傅里叶变换欧拉公式傅里叶变换绕圈记录法质心记录法傅里叶变换公式第一步&#xff1a;旋转的表示第二步&#xff1a;缠绕的表示第三步&#xff1a;质心的表示最终步&#xff1a;整理积分限和系数 参考文献 傅里叶变换 在学习傅里叶变换之前&#xff0c;我们先来了解一…...

基于python的语音识别与蓝牙通信的温控系统

基于python的语音识别与蓝牙通信的温控系统毕设项目 大家好&#xff0c;我是陈辰学长&#xff0c;一名在 Java 圈辛勤劳作的码农。今日&#xff0c;要和大家分享的是一款基于python的语音识别与蓝牙通信的温控系统毕设项目。项目源码以及部署相关事宜&#xff0c;请联系陈辰学…...

Pandas Series学习

1.Series简介 Pandas Series类似表格的列&#xff08;column&#xff09;&#xff0c;类似于一维数组&#xff0c;可以保存任何数据类型&#xff0c;具有标签&#xff08;索引&#xff09;&#xff0c;使得数据在处理分析时更具灵活性。Series数据结构是非常有用的&#xff0c;…...

为什么要探索太空?这对我们有什么好处?

几个世纪以来&#xff0c;人类一直着迷于宇宙的奥秘&#xff0c;这驱使我们冒险离开地球&#xff0c;去探索太阳系之外的未知环境。在当今世界&#xff0c;我们为什么要进行太空探索之旅这个问题&#xff0c;远不止出于单纯的好奇。 归根结底&#xff0c;太空探索是一种必要之…...

uniapp开发【选择地址-省市区功能】,直接套用即可

一、效果展示 二、代码 <template><view><view class="user_info"><view class="item"...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

Vue 3 + WebSocket 实战:公司通知实时推送功能详解

&#x1f4e2; Vue 3 WebSocket 实战&#xff1a;公司通知实时推送功能详解 &#x1f4cc; 收藏 点赞 关注&#xff0c;项目中要用到推送功能时就不怕找不到了&#xff01; 实时通知是企业系统中常见的功能&#xff0c;比如&#xff1a;管理员发布通知后&#xff0c;所有用户…...