數(shù)組的基本概念
-
數(shù)組,從字面上看,就是一組數(shù)據(jù)的意思,沒錯,數(shù)組就是用來存儲一組數(shù)據(jù)的
- 在C語言中,數(shù)組屬于構造數(shù)據(jù)類型
-
數(shù)組的幾個名詞
- 數(shù)組:一組
相同數(shù)據(jù)類型數(shù)據(jù)的有序的集合 - 數(shù)組元素: 構成數(shù)組的每一個數(shù)據(jù)。
- 數(shù)組的下標: 數(shù)組元素位置的索引(從0開始)
- 數(shù)組:一組
-
數(shù)組的應用場景
- 一個int類型的變量能保存一個人的年齡,如果想保存整個班的年齡呢?
- 第一種方法是定義很多個int類型的變量來存儲
- 第二種方法是只需要定義一個int類型的數(shù)組來存儲
- 一個int類型的變量能保存一個人的年齡,如果想保存整個班的年齡呢?
#include <stdio.h>
int main(int argc, const char * argv[]) {
/*
// 需求: 保存2個人的分數(shù)
int score1 = 99;
int score2 = 60;
// 需求: 保存全班同學的分數(shù)(130人)
int score3 = 78;
int score4 = 68;
...
int score130 = 88;
*/
// 數(shù)組: 如果需要保存`一組``相同類型`的數(shù)據(jù), 就可以定義一個數(shù)組來保存
// 只要定義好一個數(shù)組, 數(shù)組內(nèi)部會給每一塊小的存儲空間一個編號, 這個編號我們稱之為 索引, 索引從0開始
// 1.定義一個可以保存3個int類型的數(shù)組
int scores[3];
// 2.通過數(shù)組的下標往數(shù)組中存放數(shù)據(jù)
scores[0] = 998;
scores[1] = 123;
scores[2] = 567;
// 3.通過數(shù)組的下標從數(shù)組中取出存放的數(shù)據(jù)
printf("%i\n", scores[0]);
printf("%i\n", scores[1]);
printf("%i\n", scores[2]);
return 0;
}
定義數(shù)組
- 元素類型 數(shù)組名[元素個數(shù)];
// int 元素類型
// ages 數(shù)組名稱
// [10] 元素個數(shù)
int ages[10];
初始化數(shù)組
- 定義的同時初始化
- 指定元素個數(shù),完全初始化
- 其中在{ }中的各數(shù)據(jù)值即為各元素的初值,各值之間用逗號間隔
int ages[3] = {4, 6, 9};
- 不指定元素個數(shù),完全初始化
- 根據(jù)大括號中的元素的個數(shù)來確定數(shù)組的元素個數(shù)
int nums[] = {1,2,3,5,6};
- 指定元素個數(shù),部分初始化
- 沒有顯式初始化的元素,那么系統(tǒng)會自動將其初始化為0
int nums[10] = {1,2};
- 指定元素個數(shù),部分初始化
int nums[5] = {[4] = 3,[1] = 2};
- 不指定元素個數(shù),部分初始化
int nums[] = {[4] = 3};
- 先定義后初始化
int nums[3];
nums[0] = 1;
nums[1] = 2;
nums[2] = 3;
-
沒有初始化會怎樣?
- 如果定義數(shù)組后,沒有初始化,數(shù)組中是有值的,是隨機的垃圾數(shù),所以如果想要正確使用數(shù)組應該要進行初始化。
int nums[5];
printf("%d\n", nums[0]);
printf("%d\n", nums[1]);
printf("%d\n", nums[2]);
printf("%d\n", nums[3]);
printf("%d\n", nums[4]);
輸出結果:
0
0
1606416312
0
1606416414
- 注意點:
- 使用數(shù)組時不能超出數(shù)組的索引范圍使用, 索引從0開始, 到元素個數(shù)-1結束
- 使用數(shù)組時不要隨意使用未初始化的元素, 有可能是一個隨機值
- 對于數(shù)組來說, 只能在定義的同時初始化多個值, 不能先定義再初始化多個值
int ages[3];
ages = {4, 6, 9}; // 報錯
數(shù)組的使用
- 通過下標(索引)訪問:
// 找到下標為0的元素, 賦值為10
ages[0]=10;
// 取出下標為2的元素保存的值
int a = ages[2];
printf("a = %d", a);
數(shù)組的遍歷
- 數(shù)組的遍歷:遍歷的意思就是有序地查看數(shù)組的每一個元素
int ages[4] = {19, 22, 33, 13};
for (int i = 0; i < 4; i++) {
printf("ages[%d] = %d\n", i, ages[i]);
}
數(shù)組長度計算方法
- 因為數(shù)組在內(nèi)存中占用的字節(jié)數(shù)取決于其存儲的數(shù)據(jù)類型和數(shù)據(jù)的個數(shù)
- 數(shù)組所占用存儲空間 = 一個元素所占用存儲空間 * 元素個數(shù)(數(shù)組長度)
- 所以計算數(shù)組長度可以使用如下方法
數(shù)組的長度 = 數(shù)組占用的總字節(jié)數(shù) / 數(shù)組元素占用的字節(jié)數(shù)
int ages[4] = {19, 22, 33, 13};
int length = sizeof(ages)/sizeof(int);
printf("length = %d", length);
輸出結果: 4
練習
- 正序輸出(遍歷)數(shù)組
int ages[4] = {19, 22, 33, 13};
for (int i = 0; i < 4; i++) {
printf("ages[%d] = %d\n", i, ages[i]);
}
- 逆序輸出(遍歷)數(shù)組
int ages[4] = {19, 22, 33, 13};
for (int i = 3; i >=0; i--) {
printf("ages[%d] = %d\n", i, ages[i]);
}
- 從鍵盤輸入數(shù)組長度,構建一個數(shù)組,然后再通過for循環(huán)從鍵 盤接收數(shù)字給數(shù)組初始化。并使用for循環(huán)輸出查看
數(shù)組內(nèi)部存儲細節(jié)
-
存儲方式:
- 1)內(nèi)存尋址從大到小, 從高地址開辟一塊連續(xù)沒有被使用的內(nèi)存給數(shù)組
- 2)從分配的連續(xù)存儲空間中, 地址小的位置開始給每個元素分配空間
- 3)從每個元素分配的存儲空間中, 地址最大的位置開始存儲數(shù)據(jù)
- 4)用數(shù)組名指向整個存儲空間最小的地址
示例
#include <stdio.h>
int main()
{
int num = 9;
char cs[] = {'l','n','j'};
printf("cs = %p\n", &cs); // cs = 0060FEA9
printf("cs[0] = %p\n", &cs[0]); // cs[0] = 0060FEA9
printf("cs[1] = %p\n", &cs[1]); // cs[1] = 0060FEAA
printf("cs[2] = %p\n", &cs[2]); // cs[2] = 0060FEAB
int nums[] = {2, 6};
printf("nums = %p\n", &nums); // nums = 0060FEA0
printf("nums[0] = %p\n", &nums[0]);// nums[0] = 0060FEA0
printf("nums[1] = %p\n", &nums[1]);// nums[1] = 0060FEA4
return 0;
}

- 注意:字符在內(nèi)存中是以對應ASCII碼值的二進制形式存儲的,而非上述的形式。
數(shù)組的越界問題
- 數(shù)組越界導致的問題
- 約錯對象
- 程序崩潰
char cs1[2] = {1, 2};
char cs2[3] = {3, 4, 5};
cs2[3] = 88; // 注意:這句訪問到了不屬于cs1的內(nèi)存
printf("cs1[0] = %d\n", cs1[0] );
輸出結果: 88
為什么上述會輸出88, 自己按照"數(shù)組內(nèi)部存儲細節(jié)"畫圖腦補
數(shù)組注意事項
- 在定義數(shù)組的時候[]里面只能寫整型常量或者是返回整型常量的表達式
int ages4['A'] = {19, 22, 33};
printf("ages4[0] = %d\n", ages4[0]);
int ages5[5 + 5] = {19, 22, 33};
printf("ages5[0] = %d\n", ages5[0]);
int ages5['A' + 5] = {19, 22, 33};
printf("ages5[0] = %d\n", ages5[0]);
- 錯誤寫法
// 沒有指定元素個數(shù),錯誤
int a[];
// []中不能放變量
int number = 10;
int ages[number]; // 老版本的C語言規(guī)范不支持
printf("%d\n", ages[4]);
int number = 10;
int ages2[number] = {19, 22, 33} // 直接報錯
// 只能在定義數(shù)組的時候進行一次性(全部賦值)的初始化
int ages3[5];
ages10 = {19, 22, 33};
// 一個長度為n的數(shù)組,最大下標為n-1, 下標范圍:0~n-1
int ages4[4] = {19, 22, 33}
ages4[8]; // 數(shù)組角標越界
- 練習
- 從鍵盤錄入當天出售BTC的價格并計算出售的BTC的總價和平均價(比如說一天出售了10個比特幣)
數(shù)組和函數(shù)
- 數(shù)組可以作為函數(shù)的參數(shù)使用,數(shù)組用作函數(shù)參數(shù)有兩種形式:
- 一種是把數(shù)組元素作為實參使用
- 一種是把數(shù)組名作為函數(shù)的形參和實參使用
數(shù)組元素作為函數(shù)參數(shù)
- 數(shù)組的元素作為函數(shù)實參,與同類型的簡單變量作為實參一樣,如果是基本數(shù)據(jù)類型, 那么形參的改變不影響實參
void change(int val)// int val = number
{
val = 55;
}
int main(int argc, const char * argv[])
{
int ages[3] = {1, 5, 8};
printf("ages[0] = %d", ages[0]);// 1
change(ages[0]);
printf("ages[0] = %d", ages[0]);// 1
}
- 用數(shù)組元素作函數(shù)參數(shù)不要求形參也必須是數(shù)組元素
數(shù)組名作為函數(shù)參數(shù)
- 在C語言中,數(shù)組名除作為變量的標識符之外,數(shù)組名還代表了該數(shù)組在內(nèi)存中的起始地址,因此,當數(shù)組名作函數(shù)參數(shù)時,實參與形參之間不是"值傳遞",而是"地址傳遞"
- 實參數(shù)組名將該數(shù)組的起始地址傳遞給形參數(shù)組,兩個數(shù)組共享一段內(nèi)存單元, 系統(tǒng)不再為形參數(shù)組分配存儲單元
- 既然兩個數(shù)組共享一段內(nèi)存單元, 所以形參數(shù)組修改時,實參數(shù)組也同時被修改了
void change2(int array[3])// int array = 0ffd1
{
array[0] = 88;
}
int main(int argc, const char * argv[])
{
int ages[3] = {1, 5, 8};
printf("ages[0] = %d", ages[0]);// 1
change(ages);
printf("ages[0] = %d", ages[0]);// 88
}
數(shù)組名作函數(shù)參數(shù)的注意點
- 在函數(shù)形參表中,允許不給出形參數(shù)組的長度
void change(int array[])
{
array[0] = 88;
}
- 形參數(shù)組和實參數(shù)組的類型必須一致,否則將引起錯誤。
void prtArray(double array[3]) // 錯誤寫法
{
for (int i = 0; i < 3; i++) {
printf("array[%d], %f", i, array[i]);
}
}
int main(int argc, const char * argv[])
{
int ages[3] = {1, 5, 8};
prtArray(ages[0]);
}
- 當數(shù)組名作為函數(shù)參數(shù)時, 因為自動轉換為了指針類型,所以在函數(shù)中無法動態(tài)計算除數(shù)組的元素個數(shù)
void printArray(int array[])
{
printf("printArray size = %lu\n", sizeof(array)); // 8
int length = sizeof(array)/ sizeof(int); // 2
printf("length = %d", length);
}
- 練習:
- 設計一個函數(shù)int arrayMax(int a[], int count)找出數(shù)組元素的最大值
- 從鍵盤輸入3個0-9的數(shù)字,然后輸出0~9中哪些數(shù)字沒有出現(xiàn)過
- 要求從鍵盤輸入6個0~9的數(shù)字,排序后輸出