目錄
1. 一維數組
1.1 數組的概念
1.2?一維數組的創建
1.3?一維數組的初始化
1.4 數組的類型
1.5?數組下標
1.5.1?數組元素的遍歷
1.5.2 數組的輸入
1.6 一維數組在內存中的存儲
1.7 sizeof 計算數組元素個數
2. 二維數組?
2.1 二維數組的創建
2.2 二維數組的初始化
2.2.1 不完全初始化
2.2.2 完全初始化
2.2.3 按行初始化
2.2.4 初始化時省略行,但是不能省略列
2.3 二維數組的下標
2.3.1 二維數組的遍歷
2.4 二維數組在內存中的存儲
3. C99 中的變長數組
1. 一維數組
1.1 數組的概念
? ? ? ? 數組是一組相同類型元素的集合。(1)數組中存放的是 1 個或者多個元素,數組元素個數不能為 0。(2)數組中存放的數據的類型是相同的。
1.2?一維數組的創建
? ? ? ? 一維數組創建的基本語法:
type arr_name[常量值];
? ? ? ? type:數組中元素的數據類型(char,int,struct 等)。
? ? ? ? arr_name:數組名。
? ? ? ? 常量值:表示數組的大小。?
int math[20]; // 創建 math 數組用于存儲 20 人的數學成績,數據成績的類型為 int
double score[10]; // 創建 score 數組用于存儲 10 個人得分情況,得分的類型為 double
1.3?一維數組的初始化
? ? ? ? 數組在創建的時候,給定一些初始值,就叫做數組的初始化。?數組的初始化一般使用大括號,將數據放在大括號中。初始化的時候給定元素個數不能超過數組的大小。
#include <stdio.h>int main()
{int arr1[5] = {1, 2, 3, 4, 5}; // 完全初始化int arr2[6] = { 1, 5 }; // 不完全初始化:前面元素為給定的值,剩余的元素默認初始化為 0。int arr3[7]; // 定義數組的時候可以不初始化,但是默認為隨機值。return 0;
}
1.4 數組的類型
? ? ? ? 數組也是有類型的,數組算是一種自定義類型,去掉數組名留下的就是數組的類型。
int arr1[10];int arr2[12];char ch[5];
? ? ? ? arr1 數組的類型是 int [10],arr2 數組的類型是 int [12],ch 數組的類型是 char [5]。?
1.5?數組下標
? ? ? ? C 語言規定數組是有下標的,下標從 0 開始,假設數組有 n 個元素,最后一個元素的下標是 n - 1 ,下標就相當于數組元素的編號,如下:
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
? ? ? ? C 語言數組的訪問提供了一個操作符 " [] ",這個操作符叫做下標訪問操作符。?
? ? ? ? ?有下標訪問操作符,就可以輕松訪問數組的元素了。訪問下標為 7 的元素,就使用 arr[7],如下:
#include <stdio.h>int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("%d\n", arr[7]);printf("%d\n", arr[3]);return 0;
}
1.5.1?數組元素的遍歷
? ? ? ? 可以通過 for 循環 + 下標的方式對整個數組的元素進行遍歷。
#include <stdio.h>int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}
1.5.2 數組的輸入
? ? ? ? 想對數組中的元素進行修改,可以使用 scanf 進行輸入對數組的元素進行修改。
#include <stdio.h>int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int i = 0;for (i = 0; i < 10; i++){scanf("%d", &arr[i]);}for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}
? ? ? ? 注:scanf 訪問數組中單獨的一個元素的時候需要加上取地址運算符。?
1.6 一維數組在內存中的存儲
? ? ? ? 我們可以通過打印數組每個元素的地址來觀察數組在內存中是如何存儲的。
#include <stdio.h>int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int i = 0;for (int i = 0; i < 10; i++){printf("&arr[%d] = %p\n", i, &arr[i]);}return 0;
}
? ? ? ? 從輸出的結果上可以看出來,數組隨著下標的增長,地址是由小變大的,并且每兩個響鈴的元素之間相差 4,這是因為這個數組中目前存儲的數據類型為 int 類型,int 類型每一個元素需要 4 個字節進行存儲。
? ? ? ? 所以可以得出結論:數組在內存中是連續存放的。?
1.7 sizeof 計算數組元素個數
? ? ? ? 如果想直到數組的元素個數,可以使用 sizeof 關鍵字來計算類型或者變量的大小,sizeof 返回的并不是數組的元素個數,返回的是數組占據多少字節,可以通過占據的字節數除以數組中數據類型的方式來計算數組中的元素個數。
#include <stdio.h>int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int i = 0;printf("數組占用的字節數: %d\n", sizeof(arr));printf("數組中一個元素的大小: %d\n", sizeof(arr[0]));//計算?個元素的??,單位是字節int sz = sizeof(arr) / sizeof(arr[0]);printf("數組中元素的個數: %d\n", sz);return 0;
}
2. 二維數組?
2.1 二維數組的創建
? ? ? ? 把一維數組作為數組的元素時,這時候該數組就是二維數組。同理將二維數組作為數組的元素時,這時候該數組就是三位數組。二維數組以上的數組統稱為多維數組。
? ? ? ? 創建二維數組的語法如下:
type arr_name[常量值1][常量值2];
? ? ? ? ?type:表示二維數組中數據的類型。
? ? ? ? arr_name:表示二維數組的數組名。
? ? ? ? 常量1:表示二維數組的行數。
? ? ? ? 常量2:表示二維數組的列數。
int arr[3][5];
double data[2][8];
? ? ? ? 上述中 arr 表示為一個 3 行 5 列的二維數組,存儲的數據類型為 int 類型;data 表示為一個 2 行 8 列的二維數組,存儲的數據類型為 double 類型。?
2.2 二維數組的初始化
2.2.1 不完全初始化
#include <stdio.h>int main()
{int arr1[3][5] = { 1, 2, 3, 4, 5, 6, 7};int arr2[3][5] = { 0 };return 0;
}
? ? ? ? 如上,可以看出,當對二維數組進行初始化的時候,是一行一行進行初始化的,等該行初始化完,在繼續初始化下一行,并且剩余沒有初始化的元素默認初始化為 0。
2.2.2 完全初始化
#include <stdio.h>int main()
{int arr3[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 };return 0;
}
2.2.3 按行初始化
#include <stdio.h>int main()
{int arr4[3][5] = { {1,2},{3,4},{5,6} };return 0;
}
2.2.4 初始化時省略行,但是不能省略列
int arr5[][5] = { 1,2,3 };
int arr6[][5] = { 1,2,3,4,5,6,7 };
int arr7[][5] = { {1,2}, {3,4}, {5,6} };
2.3 二維數組的下標
? ? ? ? 二維數組是有行有列的,只要鎖定行和列就能鎖定數組中唯一的一個元素。
????????C語?規定,?維數組的?是從0開始的,列也是從0開始的,如下所示:
int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
? ? ? ? 如果想要訪問 7 這個數組,那么就可以通過? arr[2][4] 進行訪問。
#include <stdio.h>int main()
{int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };printf("%d\n", arr[2][4]);return 0;
}
2.3.1 二維數組的遍歷
? ? ? ? 一維數組是使用 for 循環 + 數組下標的方式進行遍歷的,那么二維數組也可以通過同樣的方式對數組進行遍歷,只是遍歷二維數組的時候需要兩層 for 循環。下列就通過遍歷的方式向二維數組中輸入數據并通過 printf 打印出來。
#include <stdio.h>int main()
{int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };int i = 0;//遍歷?//輸?for (i = 0; i < 3; i++) //產??號{int j = 0;for (j = 0; j < 5; j++) //產?列號{scanf("%d", &arr[i][j]); //輸?數據}}printf("\n");//輸出for (i = 0; i < 3; i++) //產??號{int j = 0;for (j = 0; j < 5; j++) //產?列號{printf("%d ", arr[i][j]); //輸出數據}printf("\n");}return 0;
}
2.4 二維數組在內存中的存儲
? ? ? ? 像一維數組一樣,通過打印出二維數組每個元素的地址觀察二維數組中元素的存儲方式。
#include <stdio.h>int main()
{int arr[3][5] = { 0 };int i = 0;int j = 0;for (i = 0; i < 3; i++){for (j = 0; j < 5; j++){printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);}}return 0;
}
? ? ? ? 從上述的輸出結果可以看出,每一行內部的每個元素都是相鄰的,地址之間相差 4 個字節,跨行位置處的兩個元素也是相鄰的,也只相差 4 個字節,所以二維數組中的每個元素都是連續存放的。?
3. C99 中的變長數組
? ? ? ? 在 C99 標準之前,C 語言在創建數組的時候,數組大小的指定只能使用常量、常量表達式。這樣的語法限制在創建數組的時候不夠靈活,有時候數組創建大了會造成空間浪費,有時候數組創建小了又不夠用。
? ? ? ? C99 中給出一個變長數組(variable-length array,VLA)的新特性,允許我們可以使用變量指定數組大小。
int n = a+b;
int arr[n];
? ? ? ? 上面示例中,arr 數組就是變長數組,因為它的長度取決于變量 n 的值,編譯器在編譯的時候無法確定 n 的值為多少,只有運行時才能知道? n 是多少。
? ? ? ? 變長數組的根本特征就是數組長度只有運行時才能確定,所以變長數組不能初始化。好處是在開發時不用隨意為數組指定一個估計的長度,可以在運行時為數組分配精確的長度。變?數組的意思是數組的大小是可以使?變量來指定的,在程序運?的時候,根據變量的??來指定數組的元素個數,?不是說數組的??是可變的。數組的大小?旦確定就不能再變化了。
? ? ? ? ?在 VS2022 上雖然支持大部分 C99 語法,但是沒有支持 C99 變長數組,下面是在 gcc 編譯器上測試的結果:
#include <stdio.h>int main()
{int n = 0;scanf("%d", &n);int arr[n];int i = 0;for (i = 0; i < n; i++){scanf("%d", &arr[i]);}for (i = 0; i < n; i++){printf("%d ", arr[i]);}printf("\n");return 0;
};
?