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

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.mfbz.cn/a/691352.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++学习/复习14--list的模拟实现(节点类/迭代器封装成类/list类/测试)

一、节点类 1.匿名对象 **在C中&#xff0c;匿名对象主要是通过构造函数直接生成的未命名对象实例&#xff0c;通常产生于以下三种情况&#xff1a;将对象作为值传递给函数、进行类型转换以及在函数需要返回一个对象时**。以下是对这三种情况的详细介绍&#xff1a; 1. **传…

【动态规划-BM78 打家劫舍(一)】

题目 描述 你是一个经验丰富的小偷&#xff0c;准备偷沿街的一排房间&#xff0c;每个房间都存有一定的现金&#xff0c;为了防止被发现&#xff0c;你不能偷相邻的两家&#xff0c;即&#xff0c;如果偷了第一家&#xff0c;就不能再偷第二家&#xff1b;如果偷了第二家&…

AI大模型时代,帆软引领对话式业务分析变革

大数据产业创新服务媒体 ——聚焦数据 改变商业 试想一下&#xff0c;假如用户完全不用懂技术&#xff0c;也不需要懂什么数据分析技巧&#xff0c;就可以随心所欲的进行数据分析&#xff0c;该多好。现在&#xff0c;有一个工具可以实现这个设想&#xff0c;那就是基于大模型…

嵌入式Linux系统编程 — 3.3 chown、fchown 和 lchown 函数更改文件属主

目录 1 文件属主 1.1 文件属主概念 1.2 如何查看文件属主 1.3 有效用户 ID 和有效组 ID 2 chown 函数 2.1 chown命令 2.2 chown函数 2.3 getuid 和 getgid函数 3 fchown函数 3.1 fchown函数简介 3.2 示例代码 4 lchown函数 1 文件属主 1.1 文件属主概念 Linux…

高通SDX12:Voice Over USB 功能调试

一、功能概述及使用环境 Linux PC 作为上位机,内置 SLIC基于高通 SDX12 平台的设备作为从设备,通过USB连接到 Linux PC 上,在 PC 上枚举 UAC 设备从设备进行 MO/MT Call 时,上位机使用 arecord 进行录音,音频数据通过 USB 传至上位机,上位机停止录音后再使用 aplay 进行播…

idea debug时提示”Method breakpoints may dramatically slow down debugging“的解决办法

问题现象 今天同事喊我过去看一个问题&#xff0c;项目正常启动的时候没问题&#xff0c;debug模式就卡住了&#xff0c;很久不动。我推测是哪个断点导致的&#xff0c;一看断点果然有情况。在方法上打了断点。 解决方式(Android Studio一样的解决&#xff09; 1、View Brea…

责任链模式(行为型)

目录 一、前言 二、责任链模式 三、总结 一、前言 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;也叫职责链模式&#xff0c;是一种行为型设计模式&#xff0c;职责链模式使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦…

机器学习--损失函数

损失函数&#xff08;Loss Function&#xff09;&#xff0c;也称为代价函数&#xff08;Cost Function&#xff09;或误差函数&#xff08;Error Function&#xff09;&#xff0c;是机器学习和统计学中的一个重要概念。它用于量化模型预测值与真实值之间的差异。损失函数的值…

毫米波雷达深度学习技术-1.6目标识别2

1.6.4 自动编码器和变体自动编码器 自编码器包括一个编码器神经网络&#xff0c;随后是一个解码器神经网络&#xff0c;其目的是在输出处重建输入数据。自动编码器的设计在网络中施加了一个瓶颈&#xff0c;它鼓励原始输入的压缩表示。通常&#xff0c;自编码器旨在利用数据中的…

Spring boot项目

一. Spring boot 安装地址 https://start.spring.io/ 二. 选择 三. idea配置 找到下载的文件解压缩&#xff0c;打开pom.xml(选择从idea打开)

Shell以及Shell编程

Shell的任务 ①分析命令&#xff1b; ②处理通配符、变量替换、命令替换、重定向、管道和作业控制&#xff1b; ③搜索命令并执行。 内部命令&#xff1a;内嵌在Shell中。 外部命令&#xff1a;存在于磁盘上的独立可执行文件。 #&#xff01;/bin/bash #! 称为一个幻数&…

【Vue3】理解toRef() 和 toRefs()

历史小剧场 知道可能面对的困难和痛苦&#xff0c;在死亡的恐惧中不断挣扎&#xff0c;却仍然能战胜自己&#xff0c;选择这条道路&#xff0c;这才是真正的勇气。----《明朝那些事儿》 前言 toRef 和 toRefs 是Vue3中的响应式转换工具函数 toRef: 不影响源对象的情况下&#x…

DIO控制卡,IRIG-B码卡,PCI-E总线接口卡,百兆数据采集卡

DIO控制卡 ● 4路继电器输出&#xff08;5A250VAC&#xff09; ● 4路开关量输入&#xff08;24VDC&#xff09; ● 1路IDE接口 ● 端口浪涌保护 IRIG-B码卡 ● 1路IRIG-B对时接口&#xff08;RS485/光纤&#xff09; ● 1路IEEE1588 V2对时接口&#xff08;RJ45/光纤&#…

Python在股票交易分析中的应用:布林带与K线图的实战回测

引言 在股票交易的世界中&#xff0c;技术分析是投资者们用来预测市场动向的重要工具。布林带&#xff08;Bollinger Bands&#xff09;作为一种动态波动范围指标&#xff0c;因其直观性和实用性而广受欢迎。本文将通过Python代码&#xff0c;展示如何使用布林带结合K线图来分…

数据结构之计数排序算法【图文详解】

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;LiUEEEEE                        …

【python报错】TypeError: dict.get() takes no keyword arguments

【Python报错】TypeError: dict.get() takes no keyword arguments 在Python中&#xff0c;字典&#xff08;dict&#xff09;是一种非常灵活的数据结构&#xff0c;用于存储键值对。dict.get()方法是用来从字典中获取与给定键&#xff08;key&#xff09;相关联的值&#xff0…

WordPress网站更换域名后如何重新激活elementor

在创建WordPress网站时&#xff0c;我们常常需要更改域名。但是&#xff0c;在更换域名后&#xff0c;你可能会遇到一个问题&#xff1a;WordPress后台中的Elementor插件授权状态会显示为不匹配。这时&#xff0c;就需要重新激活Elementor插件的授权。下面我会详细说明如何操作…

数据结构之ArrayList与顺序表(下)

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 目录 ArrayList的具体使用 118. 杨辉三角 扑克洗牌算法 接上篇&#xff1a;数据结构之ArrayLis…

mqtt-emqx:简单安装emqx

安装依赖 yum install -y epel-release libatomic下载 cd /chz/install/emqx wget https://www.emqx.com/en/downloads/broker/5.7.0/emqx-5.7.0-el7-amd64.tar.gz解压 mkdir -p emqx && tar -zxvf emqx-5.7.0-el7-amd64.tar.gz -C emqx后台运行 cd /chz/install/e…

ChatGPT-4o体验demo

OpenAI 最近推出了其最新的人工智能语言模型——GPT-4O。该模型是在原有 GPT-4 的基础上进行优化而成&#xff0c;旨在提升生成质量和响应速度。GPT-4O 采用了更加高效的架构设计&#xff0c;使其在处理复杂文本时表现出更快的速度和更高的准确性。GPT-4O 在训练过程中融入了最…