《C和指针》笔记31:多维数组的数组名、指向多维数组的指针、作为函数参数的多维数组

news2024/11/17 3:33:06

文章目录

  • 1. 指向多维数组的数组名
  • 2. 指向多维数组的指针
  • 3. 作为函数参数的多维数组

1. 指向多维数组的数组名

我们知道一维数组名的值是一个指针常量,它的类型是“指向元素类型的指针”,它指向数组的第1个元素。那么多维数组的数组名代表什么呢?

其实也差不多简单。唯一的区别是多维数组第1维的元素实际上是另一个数组。例如,下面这个声明:

int matrix[3][10];

matrix数组可以看作是一个一维数组,包含3个元素,只是每个元素恰好是包含10个整型元素的数组matrix这个名字的值是一个指向它第1个元素的指针,所以matrix是一个指向一个包含10个整型元素的数组的指针

在这里插入图片描述

那么下面各个表达式是什么意思呢?如果你能正确说出来,说明你对多维数组的数组名已经了如指掌了~

  1. matrix + 1

这也是一个“指向包含10个整型元素的数组的指针”,但它指向matrix的另一行:

在这里插入图片描述

为什么?因为1这个值根据包含10个整型元素的数组的长度进行调整,所以它指向matrix的下一行。

  1. *(matrix + 1)

如果对其执行间接访问操作,就如下图随箭头选择中间这个子数组:

在这里插入图片描述
事实上它标识了一个包含10个整型元素的子数组。数组名的值是个常量指针,它指向数组的第1个元素,在这个表达式中也是如此。它的类型是“指向整型的指针”。我们现在可以在下一维的上下文环境中显示它的值:

注意间接访问后还是一个指针,间接访问前是一个指向一维整型数组的指针,间接访问后是一个指向整型的指针。

在这里插入图片描述

  1. *( matrix + 1 ) + 5

前一个表达式是个指向整型值的指针,所以5这个值根据整型的长度进行调整。整个表达式的结果是一个指针,它指向的位置比原先那个表达式所指向的位置向后移动了5个整型元素。

在这里插入图片描述

  1. *( *( matrix + 1 ) + 5 )

对其执行间接访问操作,它所访问的正是图中的那个整型元素。如果它作为右值使用,你就取
得存储于那个位置的值。如果它作为左值使用,这个位置将存储一个新值。

  1. *( matrix[1] + 5 )

这个看上去吓人的表达式实际上正是我们的老朋友——下标。我们可以把子表达式matrix[1]改写为*(matrix + 1)

这个表达式是完全合法的。matrix[1]选定一个子数组,所以它的类型是一个指向整型的指针。我们对这个指针加上5,然后执行间接访问操作。

  1. matrix[1][5]

这个就是我们最常见的表达形式了。用下标代替间接访问,其含义和4、5一样。

2. 指向多维数组的指针

下面这些声明合法吗?

int vector[10], *vp = vector;
int matrix[3][10], *mp = matrix;

1个声明是合法的。它为一个整型数组分配内存,并把vp声明为一个指向整型的指针,并把它初始化为指向vector数组的第1个元素。vector和vp具有相同的类型:指向整型的指针。但是,第2个声明是非法的。它正确地创建了matrix数组,并把mp声明为一个指向整型的指针。但是,
mp的初始化是不正确的,因为matrix并不是一个指向整型的指针,而是一个指向整型数组的指针。我们应该怎样声明一个指向整型数组的指针的呢?

int (*p)[10];

下标引用的优先级高于间接访问,但由于括号的存在,首先执行的还是间接访问。所以,p是个指针,但它指向什么呢?接下来执行的是下标引用,所以p指向某种类型的数组。这个声明表达式中并没有更多的操作符,所以数组的每个元素都是整数。

我们对它执行间接访问操作时,我们得到的是个数组,对该数组进行下标引用操作得到的是一个整型值。所以p是一个指向整型数组的指针。

int (*p)[10] = matrix;

它使p指向matrix的第1行。p是一个指向拥有10个整型元素的数组的指针。当你把p与一个整数
相加时,该整数值首先根据10个整型值的长度进行调整,然后再执行加法。所以我们可以使用这个指针一行一行地在matrix中移动。

不要想当然地认为一维数组的数组名是int *,二维数组是int **,两者还是有明显差别的。

如果需要一个指针逐个访问整型元素而不是逐行在数组中移动,应该怎么办呢?下面两个声明都创建了一个简单的整型指针,并以两种不同的方式进行初始化,指向matrix的第1个整型元素。

int *pi = &matrix[0][0];
int *pi = matrix[0];

增加这个指针的值使它指向下一个整型元素。

如果你打算在指针上执行任何指针运算,应该避免这种类型的声明:

int (*p)[] = matrix;

p仍然是一个指向整型数组的指针,但数组的长度却不见了当某个整数与这种类型的指针执行指针运算时,它的值将根据空数组的长度进行调整(也就是说,与零相乘),这很可能不是你所设想的。有些编译器可以捕捉到这类错误,但有些编译器却不能。

3. 作为函数参数的多维数组

作为函数参数的多维数组名的传递方式和一维数组名相同——实际传递的是个指向数组第1个元素的指针。但是,两者之间的区别在于,多维数组的每个元素本身是另外一个数组,编译器需要知道它的维数,以便为函数形参的下标表达式进行求值。

  • 一维数组:
int vector[10];
...
func1(vector);

参数vector的类型是指向整型的指针,所以func1的原型可以是下面两种中的任何一种:

void func1( int *vec );
void func1(int vec[] );

作用于vec上面的指针运算把整型的长度作为它的调整因子。

  • 多维数组:
int matrix[3][10];
...
func2( matrix );

参数matrix的类型是指向包含10个整型元素的数组的指针。func2的原型应该是怎样的呢?

void func2( int (*mat)[10] );
void func2( int mat[][10] );

在这个函数中,mat的第1个下标根据包含10个元素的整型数组的长度进行调整,接着第2个下标根据整型的长度进行调整,这和原先的matrix数组一样。

这里的关键在于编译器必须知道第2个及以后各维的长度才能对各下标进行求值,因此在原型中必须声明这些维的长度。第1维的长度并不需要,因为在计算下标值时用不到它

在编写一维数组形参的函数原型时,你既可以把它写成数组的形式,也可以把它写成指针的形式。但是,对于多维数组,只有第1维可以进行如此选择。尤其是,把func2写成下面这样的原型是不正确的:

void func2( int **mat );

这个例子把mat声明为一个指向整型指针的指针,它和指向整型数组的指针并不是一回事。

参考

  1. 《C和指针》

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

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

相关文章

【C++】你看懂C++的类和对象了么

目录 类 默认成员函数 构造函数 析构函数 拷贝构造函数 赋值运算符重载 运算符重载 赋值运算符重载 前置和后置重载 const成员 取地址及const取地址操作符重载 再谈构造函数 构造函数体赋值 初始化列表 explicit关键字 static成员 友元 友元函数 友元类 内…

Springboot+vue的时间管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频: Springbootvue的时间管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。 项目介绍: 本文设计了一个基于Springbootvue的前后端分离的时间管理系统,采用M(model&#xff0…

计算机毕设 大数据工作岗位数据分析与可视化 - python flask

文章目录 0 前言1 课题背景2 实现效果3 项目实现3.1 概括 3.2 Flask实现3.3 HTML页面交互及Jinja2 4 **完整代码**5 最后 0 前言 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要…

使用VSCode插件开发Hyperledger Fabric智能合约(链码)

背景 开发Fabric链码对于开发者而言步骤繁琐:需要部署节点、安装链码、重启网络等操作。当前VSCode中的插件“Hyperledger Fabric Debugger”可以帮助我们迅速开发智能合约。 使用步骤 安装插件 在VSCode中安装Hyperledger Fabric Debugger插件 打开要开发链码的…

【LeetCode热题100】--35.搜索插入位置

35.搜索插入位置 使用二分查找&#xff1a; class Solution {public int searchInsert(int[] nums, int target) {int low 0,high nums.length -1;while(low < high){//注意每次循环完都要计算midint mid (low high)/2;if(nums[mid] target){return mid;}if(nums[mid]…

SE、CBAM、ECA 、CA注意力机制

文章目录 1. SE (Squeeze-and-Excitation)2. CBAM (Convolutional Block Attention Module)3. ECA (Efficient Channel Attention)4. CA (Coordinate Attention) 1. SE (Squeeze-and-Excitation) SENet是通道注意力机制的典型实现 对于SENet而言&#xff0c;其重点是获得输入进…

螺杆支撑座有哪些品牌?

螺杆支撑座是机械设备中重要的支撑部件&#xff0c;用于固定和支撑螺杆&#xff0c;以确保机械设备的稳定性和精度。以下是一些生产螺杆支撑座的品牌以及它们的特点&#xff1a; 1、NSK&#xff1a;提供各种高质量的轴承和机械部件&#xff0c;他们的螺杆支撑座采用先进的制造技…

2023.9.26 IO 文件操作详解

目录 文件 文件路径 文件类型 Java 文件操作 文件系统操作 文件内容操作 字节流 InputStream OutputStream 字符流 Reader Writer 补充 close 的必要性 Scanner 的基本了解 文件 当前指硬盘上的文件和文件夹相对于 变量 在内存中&#xff0c;文件 则是在硬盘上 …

竞赛选题 机器视觉目标检测 - opencv 深度学习

文章目录 0 前言2 目标检测概念3 目标分类、定位、检测示例4 传统目标检测5 两类目标检测算法5.1 相关研究5.1.1 选择性搜索5.1.2 OverFeat 5.2 基于区域提名的方法5.2.1 R-CNN5.2.2 SPP-net5.2.3 Fast R-CNN 5.3 端到端的方法YOLOSSD 6 人体检测结果7 最后 0 前言 &#x1f5…

sheng的学习笔记-【中文】【吴恩达课后测验】Course 2 - 改善深层神经网络 - 第二周测验

课程2_第2周_测验题 目录&#xff1a;目录 第一题 1.当输入从第8个mini-batch的第7个的例子的时候&#xff0c;你会用哪种符号表示第3层的激活&#xff1f; A. 【  】 a [ 3 ] { 8 } ( 7 ) a^{[3]\{8\}(7)} a[3]{8}(7) B. 【  】 a [ 8 ] { 7 } ( 3 ) a^{[8]\{7\}(3)} a…

【iptables 实战】9 docker网络原理分析

在开始本章阅读之前&#xff0c;需要提前了解以下的知识 阅读本节需要一些docker的基础知识&#xff0c;最好是在linux上安装好docker环境。提前掌握iptables的基础知识&#xff0c;前文参考【iptables 实战】 一、docker网络模型 docker网络模型如下图所示 说明&#xff1…

23.2 Bootstrap框架3

1.卡片 1.1卡片样式 在Bootstrap 5中, .card, card-header, .card-body, .card-footer类是用于创建卡片样式.下面是这些类的简单介绍: * 1. .card: 用于创建一个基本的卡片容器它作为一个包裹元素,通常与其他卡片类一起使用.* 2. .card-header: 用于创建卡片的头部部分.通常在…

双重差分模型(DID)论文写作指南与操作手册

手册链接&#xff1a;双重差分模型&#xff08;DID&#xff09;论文写作指南与操作手册https://www.cctalk.com/m/group/90983583?xh_fshareuid60953990 简介&#xff1a; 当前&#xff0c;对于准应届生们来说&#xff0c;毕设季叠加就业季&#xff0c;写作时间显得十分宝贵…

Sentinel安装

Sentinel 微服务保护的技术有很多&#xff0c;但在目前国内使用较多的还是Sentinel&#xff0c;所以接下来我们学习Sentinel的使用。 1.介绍和安装 Sentinel是阿里巴巴开源的一款服务保护框架&#xff0c;目前已经加入SpringCloudAlibaba中。官方网站&#xff1a; 首页 | Se…

Sublime Text 4 for Mac激活下载

Sublime Text for Mac是一款适用于Mac平台的文本编辑器。它具有快速的性能和丰富的功能&#xff0c;可以帮助用户快速进行代码编写和文本编辑。 软件下载&#xff1a;Sublime Text 4 for Mac激活下载 该软件具有直观的界面和强大的功能&#xff0c;包括多行选择、代码折叠、自动…

【数据开发】DW数仓分层设计架构与同步策略(ODS、DWD、DWS等字段含义)

文章目录 1、什么是数据仓库&#xff08;DW&#xff09;2、DW分层设计架构&#xff08;ODS&#xff0c;DWD&#xff0c;DWS&#xff09;3、数仓同步策略 1、什么是数据仓库&#xff08;DW&#xff09; Data warehouse&#xff08;可简写为DW或者DWH&#xff09;数据仓库是什么…

【软考】系统集成项目管理工程师(六)项目整体管理【6分】

一、 前言 1、项目管理三从四得 2、ITO共性总结 1、上一个过程的输出大部分是下-个过程的输入 2、计划和文件是不一样的 (每个输入都有计划和文件) 3、被批准的变更请求约等于计划 4、在执行和监控过程产生新的变更请求(变更请求包括变什么和怎么变&#xff0c;这是变更请求和…

[JAVAee]SpringBoot-AOP

目录 Spring AOP ​编辑AOP适用场景 AOP的组成 连接点(Join Point) 切点(Pointcut) 通知(Advice) Spring AOP的实现 添加依赖 定义切面与切点 切点表达式的说明 定义相关的通知 Spring AOP AOP(Aspect Oriented Programming)是面向切面编程,是一种设计思想.对某一类…

联想Lenovo 威6 15-ITL(82F2)原厂Win10系统

lenovo联想原装出厂系统 自带所有驱动、出厂主题壁纸LOGO、Office办公软件、联想电脑管家等预装程序 下载链接&#xff1a;https://pan.baidu.com/s/1darORHmIyAXkD7HvKRNHNw?pwddh6e 所需要工具&#xff1a;16G或以上的U盘 文件格式&#xff1a;ISO 文件大小&#xff1a;11.…

号卡推广管理系统源码/手机流量卡推广网站源码/PHP源码+带后台版本+分销系统

源码简介&#xff1a; 号卡推广管理系统源码/手机流量卡推广网站源码&#xff0c;基于PHP源码&#xff0c;而且它是带后台版本&#xff0c;分销系统。运用全新UI流量卡官网系统源码有后台带文章。 这个流量卡销售网站源码&#xff0c;PHP流量卡分销系统&#xff0c;它可以支持…