09-數組的含義以及零長數組變長數組與多維數組
文章目錄
- 09-數組的含義以及零長數組變長數組與多維數組
- 一、數組名的含義
- 1.1 表示整個數組的首地址
- 1.2 表示整個數組首元素的首地址
- 二、數組下標
- 字符串常量
- 三、零長數組
- 3.1 示例
- 四、變長數組
- 4.1 示例
- 五、多維數組
- 5.1 定義與初始化
- 5.2 引用元素
- 5.3 實例講解
- 5.4 總結
一、數組名的含義
1.1 表示整個數組的首地址
在某些特定情況下,數組名表示整個數組的首地址
:
- 數組定義的時候
- 在使用
sizeof
運算符中:使用 sizeof 運算符求的是整個數組的大小 - 在取地址符中
&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;
}
注意:
- 因為數組的長度未確定, 因此它不允許初始化。
- 在使用的時候可以通過該變長數組來有限的節省內存空間。
五、多維數組
概念:多維數組是指數組的元素也是數組,例如二維數組、三維數組等。
示例:
int a[2][3];
這個二維數組 a
包含了 2 個一維數組,每個一維數組有 3 個元素。
5.1 定義與初始化
-
定義和初始化帶有明確的嵌套大括號:
int arr[2][3] = { {1, 2, 3}, {4, 5, 6} };
上述語句定義了一個包含 2 行 3 列的二維數組,并初始化其值為:
arr = { {1, 2, 3},{4, 5, 6} }
-
省略嵌套大括號的初始化:
int arr1[2][3] = { 1, 2, 3, 4, 5, 6 };
上述語句的效果等同于:
arr1 = { {1, 2, 3},{4, 5, 6} }
5.2 引用元素
-
通過下標引用:
arr[0][0] = 100;
-
通過指針偏移引用:
*(*(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;
}
分析:
-
直接訪問二維數組的元素:
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]
訪問和打印二維數組的元素。 -
使用指針偏移訪問元素:
for (int i = 0; i < 6; i++) {printf("*(*(arr + 0) + %d): %d\t", i, *(*(arr + 0) + i)); }
這個循環通過指針偏移來訪問二維數組的元素。
*(arr + 0)
獲取二維數組的第一行,*(*(arr + 0) + i)
獲取第一行第i
個元素。 -
另一種指針偏移的訪問方式:
for (int i = 0; i < 6; i++) {printf("*(*(arr + %d)): %d\t", i, *(*(arr + i / 3) + i % 3)); }
這個循環同樣通過指針偏移來訪問元素,但它通過
i / 3
計算行號,通過i % 3
計算列號。 -
將二維數組的首元素地址賦給指針
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標準引入了柔性數組成員,但零長數組仍在遺留代碼中使用。
-
變長數組:在定義時長度由變量決定,定義后長度不再改變。注意:變長數組不能初始化。
-
多維數組:數組元素也是數組,可以通過下標和指針偏移訪問。