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" 字符串常量首元素的首地址加 1printf("%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");// 將二維數組的首元素地址賦給指針 pint *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.pswp.cn/web/24627.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/24627.shtml
英文地址,請注明出處:http://en.pswp.cn/web/24627.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

nodejs---fs模塊,文件讀寫操作詳解,自定義一個文件寫入方法

fs模塊導入 Node.js 同時支持 CommonJS 和 ES 模塊系統&#xff08;自 Node.js v12 以來&#xff09; // 兩種模塊導入方式 import * as fs from fs;// Es6:這種方式需要在package.json中配置"type": "module" const fs require(fs);// commonJs:如果你…

golang協程工作池處理多任務示例

1. 工作方法實現 // 工作線程 // id : 線程號 // jobs : 任務通道 (chan) // results: 完成結果通道 (chan) func worker(id int, jobs <-chan int, results chan<- int) {//遍歷任務for j : range jobs {fmt.Println("工作協程: ", id, "啟動任務: &quo…

oracle中如何查詢特定日期?

1. select last_day(to_date(20230101,YYYYMMDD)) from dual; select last_day(to_date(V_END_DATE,YYYYMMDD)) from dual; --查詢任意一天 當月的最后一天 2. select to_char(to_date(20230101,YYYYMMDD)-1,YYYYMMDD) INTO V_START_DATE FROM DUAL; select to_char(to_dat…

vscode輸出控制臺中文顯示亂碼最有效解決辦法

當VSCode的輸出控制臺中文顯示亂碼時&#xff0c;一個有效的解決辦法是通過設置環境變量來確保編碼的正確性。以下是解決方式&#xff1a; 首先&#xff0c;設置環境變量以修正亂碼問題&#xff1a; 如果上述方法沒有解決亂碼問題&#xff0c;請繼續以下步驟&#xff1a; 右鍵…

技術革命的十年:計算機、互聯網、大數據、云計算與AI

近10年來&#xff0c;計算機、互聯網、大數據、云計算和人工智能等技術領域發展迅速&#xff0c;帶來了巨大的變革和創新。以下是各個領域的發展歷史、現狀、問題瓶頸、未來趨勢以及可能的奇點。 計算機技術&#xff1a; 發展歷史&#xff1a; 過去&#xff1a;過去十年間&am…

HTML5表單元素:重塑數據收集的藝術

HTML5為網頁表單帶來了革命性的變化&#xff0c;不僅增強了用戶體驗&#xff0c;也為開發者提供了更加強大和靈活的工具來收集和驗證數據。本文將深入解析HTML5中新增和改進的表單元素&#xff0c;通過實例展示它們如何提升表單功能和交互性。 1. 新增表單元素 <input>…

SVN中trunk,branch,tag

SVN trunk(主線) branch(分支) tag(標記) 用法詳解和詳細操作步驟_svn 分支-CSDN博客 場景: 項目的1.0版本已經完成開發,測試,并上線了. 接到了新需求,要修改多個文件的代碼. 你寫了一段時間的時候,用戶或測試人員反饋, 1.0版本有重大bug要修復,修復好后立刻上線. 此時應該怎么…

RocketMQ的安裝

首先到RocketMQ官網下載頁面下載 | RocketMQ (apache.org)&#xff0c;本機解壓縮&#xff0c;作者在這里用的是最新的5.2.0版本。按照如下步驟安裝。 1、環境變量配置rocket mq地址 ROCKETMQ_HOME D:\rocketmq-all-5.2.0-bin-release 在變量path中添加”%ROCKETMQ_HOME%\bi…

免費數據庫同步軟件

在信息化日益發展的今天&#xff0c;數據同步成為了企業和個人用戶不可或缺的一部分。數據庫同步軟件作為數據同步的重要工具&#xff0c;能夠幫助我們實現不同數據庫系統之間的數據復制和同步&#xff0c;確保數據的一致性和完整性。本文將介紹幾款免費數據庫同步軟件&#xf…

ES5/ES6 的繼承除了寫法以外還有什么區別?

一、主要區別 ES5 的繼承實質上是先創建子類的實例對象&#xff0c; 然后再將父類的方法添加 到 this 上&#xff08;Parent.apply(this)&#xff09; . ES6 的繼承機制完全不同&#xff0c; 實質上是先創建父類的實例對象 this&#xff08;所以必 須先調用父類的 super()方法…

C#根據反射生成sql語句(Update語句)

今天有人問我Update語句怎么搞&#xff0c;想了一下大致思路就是用特性去標識一下&#xff0c;主鍵&#xff0c;然后再去用反射的方式拼sql語句。 在C#中&#xff0c;我們可以使用特性&#xff08;Attributes&#xff09;來標識一個類的屬性作為該類的主鍵&#xff08;Primary…

旅游卡系統開發搭建

旅游卡系統的開發搭建是一個涉及多個步驟和關鍵因素的復雜過程。以下是關于旅游卡系統開發搭建的詳細步驟和要點&#xff1a; 一、需求分析 目標用戶調研&#xff1a;深入調研目標用戶&#xff0c;了解他們的需求和痛點&#xff0c;從而確定系統的功能和特點。功能確定&#…

數據分析必備:一步步教你如何用Pandas做數據分析(20)

1、Pandas 分類數據 Pandas 分類數據的操作實例 數據通常實時包含重復的文本列。性別&#xff0c;國家/地區和代碼等功能始終是重復的。這些是分類數據的示例。 分類變量只能采用有限的且通常是固定數量的可能值。除固定長度外&#xff0c;分類數據可能還具有順序&#xff0c;…

elasticsearch安裝與使用(1)-使用docker安裝Elasticsearch

ES的優點&#xff1a; 1、分布式準實時2、提供REST風格的API接口&#xff0c;是用戶可解借助任何語言使用https對ES執行請求來完成搜索任務&#xff1b;3、提供聚合功能 1、Elasticsearch安裝 docker network create elastic docker pull docker.elastic.co/elasticsearch/e…

MySQL入門學習-聚合和分組.計數(COUNT()函數)

在 MySQL 中&#xff0c;聚合和分組是用于對數據進行匯總和分析的強大功能。聚合函數可以計算數據的總和、平均值、最小值、最大值等統計信息&#xff0c;而分組則可以將數據按照特定的字段進行分組&#xff0c;然后對每個分組進行聚合計算。計數&#xff08;COUNT() 函數&…

【MYSQL系列】mysql中text,longtext,mediumtext區別

【MYSQL系列】mysql中text,longtext,mediumtext區別 在MySQL數據庫中&#xff0c;TEXT、LONGTEXT和MEDIUMTEXT都是用于存儲大量文本數據的字段類型。它們之間的主要區別在于可存儲的數據大小和性能方面的差異。本文將探討這些字段類型的特點、使用場景和一些最佳實踐。 TEXT類…

貪心(不相交的開區間、區間選點、帶前導的拼接最小數問題)

目錄 1.簡單貪心 2.區間貪心 不相交的開區間 1.如何刪除&#xff1f; 2.如何比較大小 區間選點問題 3.拼接最小數 1.簡單貪心 比如&#xff1a;給你一堆數&#xff0c;你來構成最大的幾位數 2.區間貪心 不相交的開區間 思路&#xff1a; 首先&#xff0c;如果有兩個…

代碼隨想錄算法訓練營第三十二天|LeetCode122 買賣股票的最佳時機Ⅱ、LeetCode55 跳躍游戲、LeetCode45 跳躍游戲Ⅱ

題1&#xff1a; 指路&#xff1a;122. 買賣股票的最佳時機 II - 力扣&#xff08;LeetCode&#xff09; 思路與代碼&#xff1a; 基本思路&#xff1a;一天買入一天賣出&#xff0c;得到每部分正利潤作為局部最優解&#xff0c;例如prices[7, 1, 5, 3, 6, 4]中&#xff0c;…

山東大學軟件學院項目實訓-創新實訓-基于大模型的旅游平臺(三十)- 微服務(10)

目錄 12.5 RestClient操作索引庫 12.5.1創建庫 12.5.2 刪除索引庫 12.5.3 判斷是否存在 12.6 RestClient操作文檔 12.6.1 新增文檔 12.6.2 查詢文檔 12.6.3 修改文檔 12.6.4 刪除文檔 12.6.5 批量導入文檔 12.5 RestClient操作索引庫 酒店mapping映射 ?PUT /hotel{&…

shell簡介

一、Shell 概念定義 Shell 是用 C 語言編寫的程序&#xff0c;是用戶使用 Linux 的橋梁&#xff0c;既是命令語言又是程序設計語言。 shell 腳本為 Shell 編寫的腳本程序&#xff0c;常說的 shell 通常指 shell 腳本。 包含一系列命令的文本文件&#xff0c;這些命令按照特定…