09-数组的含义以及零长数组变长数组与多维数组

news2024/11/26 16:23:50

09-数组的含义以及零长数组变长数组与多维数组

文章目录

  • 09-数组的含义以及零长数组变长数组与多维数组
    • 一、数组名的含义
      • 1.1 表示整个数组的首地址
      • 1.2 表示整个数组首元素的首地址
    • 二、数组下标
      • 字符串常量
    • 三、零长数组
      • 3.1 示例
    • 四、变长数组
      • 4.1 示例
    • 五、多维数组
      • 5.1 定义与初始化
      • 5.2 引用元素
      • 5.3 实例讲解
      • 5.4 总结

一、数组名的含义

1.1 表示整个数组的首地址

在某些特定情况下,数组名表示整个数组的首地址

  1. 数组定义的时候
  2. 在使用 sizeof 运算符中:使用 sizeof 运算符求的是整个数组的大小
  3. 在取地址符中 &arr
#include <stdio.h>

int main() {
    int arr[10];

    // 在数组定义的时候
    printf("数组定义时的地址: %p\n", (void*)arr);

    // 使用 sizeof 运算符
    int len = sizeof(arr);
    printf("数组的大小: %d\n", len);

    // 取地址符中
    int (*p)[10] = &arr;
    printf("取地址符中: %p\n", (void*)p);

    return 0;
}

1.2 表示整个数组首元素的首地址

在其他情况下,数组名表示数组的首元素的首地址

#include <stdio.h>

int main() {
    int arr[10];

    // 表示数组的首元素的首地址
    int *p1 = arr;
    printf("数组首元素的地址: %p\n", (void*)p1);

    return 0;
}

二、数组下标

数组下标只是编译器提供的一种简写,实际上如下:

#include <stdio.h>

int main() {
    int a[100];
    a[10] = 250;   // ==> 等价于 *(a + 10) = 250
    *(a + 10) = 250;
    *(10 + a) = 250;
    10[a] = 250;

    printf("a[10] = %d\n", a[10]);

    return 0;
}

字符串常量

字符串常量是一个被存放在常量区的字符串,实际上也可以称为一个匿名数组。匿名数组,同样满足数组名的含义。
在这里插入图片描述

#include <stdio.h>

int main() {
    char *msg2 = "Hello Even";     // 输出:"Hello Even" 字符串常量首元素的首地址
    char *msg1 = "Hello Even" + 1; // 输出:"ello Even" 字符串常量首元素的首地址加 1

    printf("%s\n", "Hello Even");  // "Hello Even" 字符串常量首元素的首地址
    printf("%s\n", &"Hello Even"); // "Hello Even" 字符串常量的整个数组的地址

    // 访问字符串中的某个字符
    printf("%c\n", "Hello Even"[6]); // 输出: 'E'

    return 0;
}

注意事项:

  • 数组名的双重含义
    • 表示整个数组的首地址时:在数组定义、sizeof 运算符、取地址符 &arr 中。
    • 表示数组首元素的首地址时:在大多数其他情况下。
  • 数组下标运算a[i] 等价于 *(a + i),甚至 i[a] 也是合法的。
  • 字符串常量:可以被视为匿名数组,数组名(即字符串字面值)表示其首元素的首地址。

三、零长数组

零长数组(zero-length array)是数组长度为0的数组,通常用于结构体的最后一个成员作为可变长度数据的入口

用途:用于结构体中的可变长度数据。尽管C99标准已经引入了柔性数组成员(flexible array member),零长数组仍在一些遗留代码中使用。

3.1 示例

#include <stdio.h>
#include <stdlib.h>

struct node {
    int a;
    char b;
    float c;
    int len;
    char arr[0]; // 零长数组
};

int main() {
    struct node *p = malloc(sizeof(struct node) + 20); // 分配足够的内存-->+ 20 就是在原有的基础上增加20字节
    p->len = 20; // 设置额外增长的长度为20

    // 使用零长数组
    for (int i = 0; i < p->len; i++) {
        p->arr[i] = 'A' + i;
    }

    for (int i = 0; i < p->len; i++) {
        printf("%c ", p->arr[i]);
    }
    printf("\n");

    free(p);
    return 0;
}

在这里插入图片描述

四、变长数组

概念:变长数组(variable-length array,VLA)是其长度在定义时由一个变量决定的数组。定义之后,其长度不能再改变。

重点: 变长数组并不是说在任意时候他的长度可以随意变化, 实际上只是在定义之前
数组的长度是未知的有一个变量来决定, 但是定义语句过后变长数组的长度由定义那一刻
变量的大小来决定。

4.1 示例

#include <stdio.h>

int main() {
    int a = 200;// // a 作为一个普通的变量 , 200 则可以作为arr 的长度
    a = 99; // 99 可以作为 arr 的长度
    int arr[a]; // a 当前是99,因此数组长度为99
//从此以后该数组的长度已经确定为99 不会再变换
    for (int i = 0; i < a; i++) {
        arr[i] = i;
    }

    for (int i = 0; i < a; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    a = 10 ;  // a = 10 并不会影响数组的长度
    return 0;
}

注意:

  1. 因为数组的长度未确定, 因此它不允许初始化
  2. 在使用的时候可以通过该变长数组来有限的节省内存空间。

五、多维数组

概念:多维数组是指数组的元素也是数组,例如二维数组、三维数组等。
在这里插入图片描述

示例:

int a[2][3];

这个二维数组 a 包含了 2 个一维数组,每个一维数组有 3 个元素。

5.1 定义与初始化

  1. 定义和初始化带有明确的嵌套大括号:

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

    上述语句定义了一个包含 2 行 3 列的二维数组,并初始化其值为:

    arr = { {1, 2, 3},
            {4, 5, 6} }
    
  2. 省略嵌套大括号的初始化:

    int arr1[2][3] = { 1, 2, 3, 4, 5, 6 };
    

    上述语句的效果等同于:

    arr1 = { {1, 2, 3},
             {4, 5, 6} }
    

5.2 引用元素

  1. 通过下标引用:

    arr[0][0] = 100;
    
  2. 通过指针偏移引用:

    *(*(arr + 0) + 0) = 100;
    

5.3 实例讲解

#include <stdio.h>

int main() {
    int arr[2][3] = { {1, 2, 3}, {4, 5, 6} };
    int arr1[2][3] = { 1, 2, 3, 4, 5, 6 };

    // 遍历并打印二维数组的元素
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            printf("arr[%d][%d]: %d\t", i, j, arr[i][j]);
        }
        printf("\n");
    }
    printf("\n");

    // 使用指针偏移访问数组元素
    for (int i = 0; i < 6; i++) {
        printf("*(*(arr+0) + %d): %d\t", i, *(*(arr+0) + i));
    }
    printf("\n");

    // 使用指针偏移访问数组元素的另一种方式
    for (int i = 0; i < 6; i++) {
        printf("*(*(arr + %d)): %d\t", i, *(*(arr + i / 3) + i % 3));
    }
    printf("\n");

    // 将二维数组的首元素地址赋给指针 p
    int *p = &arr[0][0];
    for (int i = 0; i < 6; i++) {
        printf("*(p + %d): %d\n", i, *(p + i));
    }

    return 0;
}

分析:

  1. 直接访问二维数组的元素

    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            printf("arr[%d][%d]: %d\t", i, j, arr[i][j]);
        }
        printf("\n");
    }
    

    这个循环直接通过 arr[i][j] 访问和打印二维数组的元素。

  2. 使用指针偏移访问元素

    for (int i = 0; i < 6; i++) {
        printf("*(*(arr + 0) + %d): %d\t", i, *(*(arr + 0) + i));
    }
    

    这个循环通过指针偏移来访问二维数组的元素。*(arr + 0) 获取二维数组的第一行,*(*(arr + 0) + i) 获取第一行第 i 个元素。

  3. 另一种指针偏移的访问方式

    for (int i = 0; i < 6; i++) {
        printf("*(*(arr + %d)): %d\t", i, *(*(arr + i / 3) + i % 3));
    }
    

    这个循环同样通过指针偏移来访问元素,但它通过 i / 3 计算行号,通过 i % 3 计算列号。

  4. 将二维数组的首元素地址赋给指针 p 并访问

    int *p = &arr[0][0];
    for (int i = 0; i < 6; i++) {
        printf("*(p + %d): %d\n", i, *(p + i));
    }
    

    p 指向二维数组的首元素(第一个元素 arr[0][0]),通过 *(p + i) 访问所有元素。这种方法将二维数组视为一个一维数组。

5.4 总结

  • 多维数组:本质上是数组的数组。

  • 定义与初始化:可以使用嵌套大括号或直接平铺的方式。

  • 引用元素:可以使用下标或指针偏移。

  • 指针与多维数组:可以将多维数组的地址赋给指针,通过指针进行遍历和访问。
    总结

  • 零长数组:用于结构体末尾作为可变长度数据入口,虽然C99标准引入了柔性数组成员,但零长数组仍在遗留代码中使用。

  • 变长数组:在定义时长度由变量决定,定义后长度不再改变。注意:变长数组不能初始化。

  • 多维数组:数组元素也是数组,可以通过下标和指针偏移访问。

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

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

相关文章

UML实现图-部署图

概述 部署图(Deployent Diagram)描述了运行软件的系统中硬件和软件的物理结构。部署图中通常包含两种元素:节点和关联关系&#xff0c;部署图中每个配置必须存在于某些节点上。部署图也可以包含包或子系统。 节点是在运行时代表计算机资源的物理元素。节点名称有两种:简单名和…

APP开发技术的变迁史

随着移动互联网的迅猛发展&#xff0c;APP&#xff08;应用程序&#xff09;已经成为人们日常生活中不可或缺的一部分。从最初的简单工具到如今的智能平台&#xff0c;APP开发技术在这十年间经历了翻天覆地的变化。本文将从多个维度探讨近十年来APP开发技术的变迁史&#xff0c…

NVeloDocx一个基于NVelocity的word模版引擎

NVeloDocx是一个基于NVelocity的Word模版引擎&#xff0c;目前主要是用于E6低代码开发平台供用户轻松制作各种Word报告模版。 有以下优点&#xff1a; 1、完全的NVelocity语法&#xff1b; 2、直接在Word中写NVelocity脚本&#xff0c;使用非常非常方便&#xff1b; 3、完全兼…

阅读笔记:Life of a Pixel

PPT地址&#xff1a;​​​​​​​​​​​​​​https://docs.google.com/presentation/d/1boPxbgNrTU0ddsc144rcXayGA_WF53k96imRH8Mp34Y/edit?uspsharing 这份PPT讲述了Chromium浏览器内核中html文档渲染成像素的主要过程。网上有很多介绍和转载&#xff0c;内容非常硬核。…

数据结构及研究

**数据结构是计算机存储、组织数据的方式&#xff0c;它是相互之间存在一种或多种特定关系的数据元素的集合**Θic-1ΘΘic-2ΘΘic-3ΘΘic-4ΘΘic-5Θ。 数据结构这一概念在计算机科学领域扮演着至关重要的角色&#xff0c;它不仅决定了数据在计算机内部的存储方式&#xf…

lubuntu / ubuntu 配置静态ip

一、查看原始网络配置信息 1、获取网卡名称 ifconfig 2、查询网关IP route -n 二、编辑配置文件 去/etc/netplan目录找到配置文件&#xff0c;配置文件名一般为01-network-manager-all.yaml sudo vim /etc/netplan/01-network-manager-all.yaml文件打开后内容如下 # This …

玄机平台应急响应—apache日志分析

1、前言 apache的日志一共有两个&#xff0c;一个是access.log&#xff0c;这个日志记录了所有对Web服务器的访问&#xff0c;被入侵时重点排查这个。另一个是error.log&#xff0c;错误日志记录了服务器运行期间遇到的各种错误&#xff0c;以及一些普通的诊断信息&#xff0c…

一个简单的消息队列

目录 原理 实现代码 示例 原理 消息队列是一个先进先出栈&#xff0c;每次都处理第一项&#xff0c;处理完了过后会删除这个消息&#xff0c;这是一个简单的消息队列图&#xff1a; 实现代码 首先消息队列需要一个队列&#xff0c;我们用Python里的列表&#xff1a; self.…

贪心(不相交的开区间、区间选点、带前导的拼接最小数问题)

目录 1.简单贪心 2.区间贪心 不相交的开区间 1.如何删除&#xff1f; 2.如何比较大小 区间选点问题 3.拼接最小数 1.简单贪心 比如&#xff1a;给你一堆数&#xff0c;你来构成最大的几位数 2.区间贪心 不相交的开区间 思路&#xff1a; 首先&#xff0c;如果有两个…

vue-router 源码分析——2. router-link 组件是如何实现导航的

这是对vue-router 3 版本的源码分析。 本次分析会按以下方法进行&#xff1a; 按官网的使用文档顺序&#xff0c;围绕着某一功能点进行分析。这样不仅能学习优秀的项目源码&#xff0c;更能加深对项目的某个功能是如何实现的理解。这个对自己的技能提升&#xff0c;甚至面试时…

VL830 USB4 最高支持40Gbps芯片功能阐述以及原理图分享

前文斥巨资拆了一个扩展坞供大家参考。其中核心即为本文要说的这个VL830,USB4的HUB芯片。 拆解报告传送门&#xff1a;USB4 Gen3x2 最高40Gbps传输速率的HUB扩展坞拆解分析 OK&#xff0c;闲话少叙。直接进入主题&#xff0c;我就直接翻译规格书了。 VL830是一款USB4端点设备…

Java学习54-关键字this的使用

this是什么 this的作用&#xff1a; 它在方法(准确的说是实例方法或非static的方法)内部使用&#xff0c;表示调用该方法的对象 它在构造器内部使用&#xff0c;表示该构造器正在初始化的对象 this可以调用的结构&#xff1a;成员变量、方法和构造器 什么时候使用this 实…

深度学习:如何静悄悄地改变我们的日常生活

深度学习 深度学习&#xff1a;如何静悄悄地改变我们的日常生活一、消费电子产品智能手机与个人助理娱乐与社交媒体 二、医疗健康三、汽车与交通四、公共安全五、总结 深度学习&#xff1a;如何静悄悄地改变我们的日常生活 在近年来&#xff0c;深度学习技术因其强大的数据处理…

fmsh:1 memorytest测试内存工程使用说明

1、如何导出 从procise中导出内存测试工程&#xff1a;memtest 点击ok按钮导出memtest工程成功。 2、引导iar启动&#xff0c;进入工程 1&#xff09;确保已经关联了iar工具 2&#xff09;启动iar 工程目录如下&#xff1a; 3、修改内存测试大小 4、压力测试下&#xff…

OS复习笔记ch7-3

承接上文我们讲完了页式管理和段式管理&#xff0c;接下来让我们深入讲解一下快表和二级页表 快表 快表和计算机组成原理讲的Cache原理如出一辙。为了减少访存的次数&#xff0c;OS在访问页面的时候创建了快表&#xff08;Translation Lookaside Buffer &#xff0c;简称TLB&…

大数据湖一体化平台整体建设方案(PPT原件)

背 景&#xff1a;大数据湖的发展背景与建设理念 体 系&#xff1a;大数据湖体系规划与建设思路 生态圈&#xff1a;探索新兴业务入湖建设模式 共 享&#xff1a;大数据湖统一访问共享规划 运 营&#xff1a;大数据湖一体化运营管理建设 软件全套资料部分文档清单&…

centos7 安装 mysql5.7 LTS

centos7 安装 mysql5.7 LTS 参考&#xff1a; https://blog.csdn.net/EB_NUM/article/details/105425622 可以在运行安装程序之前导入密钥&#xff1a; sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022第一步、下载MySQL 安装包&#xff1a; sudo wget h…

Vue第三方库与插件实战手册

title: Vue第三方库与插件实战手册 date: 2024/6/8 updated: 2024/6/8 excerpt: 这篇文章介绍了如何在Vue框架中实现数据的高效验证与处理&#xff0c;以及如何集成ECharts、D3.js、Chart.js等图表库优化数据可视化效果。同时&#xff0c;探讨了Progressive Web App(PWA)的接入…

【传知代码】DETR[端到端目标检测](论文复现)

前言&#xff1a;想象一下&#xff0c;当自动驾驶汽车行驶在繁忙的街道上&#xff0c;DETR能够实时识别出道路上的行人、车辆、交通标志等目标&#xff0c;并准确预测出它们的位置和轨迹。这对于提高自动驾驶的安全性、减少交通事故具有重要意义。同样&#xff0c;在安防监控、…

【Python】解决Python报错:KeyError: ‘username‘

​​​​ 文章目录 引言1. 错误详解2. 常见的出错场景2.1 用户输入处理错误2.2 动态数据源 3. 解决方案3.1 使用 get() 方法3.2 检查键是否存在 4. 预防措施4.1 数据验证4.2 使用默认字典 (defaultdict) 结语 引言 在Python开发中&#xff0c;处理字典时遇到 KeyError 是一种…