1. 初始化
1.1 整體初始化
試一下下面三段代碼跟狱,分析輸出。
- 代碼一
int arr[12];
for(int i=0;i<12;++i){
printf("%d ",arr[i]);
}
- 代碼二
int arr[12] = {0};
for(int i=0;i<12;++i){
printf("%d ",arr[i]);
}
- 代碼三
int arr[12] = {2};
for(int i=0;i<12;++i){
printf("%d ",arr[i]);
}
結(jié)論:
- 數(shù)組未初始化丧靡,數(shù)組里面的值都是隨機值祖能。
- 數(shù)組初始化為
{0}
歉秫,數(shù)組里面的值都是0
。 - 數(shù)組初始化為
{非零值}
养铸,數(shù)組里面第一個值是非零值
雁芙,其他的值都是0
。
1.2 部分初始化
試一下代碼揭厚,分析輸出却特。
int arr[12] = {[2]=2,[5]=5};
for(int i=0;i<12;++i){
printf("%d ",arr[i]);
}
指定下標的值被賦值,其他的值都是0
筛圆。這是C99語法。
1.3 大小
試一下椿浓,下面代碼分析結(jié)果太援。
char carr[12];
int iarr[12];
double farr[12];
printf("carr = %d\n",sizeof(carr));
printf("iarr = %d\n",sizeof(iarr));
printf("farr = %d\n",sizeof(farr));
sizeof
給出整個數(shù)組所占據(jù)的內(nèi)容的大小。數(shù)組大小=元素大小*數(shù)組個數(shù)扳碍。
問題:已知數(shù)組arr
提岔,如何求出數(shù)組元素個數(shù)?
1.4 賦值
試一下下面的代碼
int days[]={31,28,31,30,31,30,31,31,30,31,30,31};
int arr = days;
2. 數(shù)組與指針
2.1 數(shù)組名是地址
數(shù)組名是數(shù)組第一個元素的地址笋敞。
int arr[] = {1,2,3,4,5,6,7,8};
printf("&arr=%p\n",&arr);
printf("arr=%p\n",arr);
printf("&arr[0]=%p\n",&arr[0]);
數(shù)組下標實現(xiàn)的操作指針也可以實現(xiàn)碱蒙。數(shù)組名+下標
表示下標i
元素的地址。
No. | 操作 | 下標 | 指針 |
---|---|---|---|
1 | 第i 個元素值 |
arr[i] |
*(arr+i) |
2 | 第i 個元素地址 |
&arr[i] |
arr+i |
所以夯巷,遍歷數(shù)組可以是
int arr[] = {1,2,3,4,5,6,7,8};
for(int i=0;i<8;++i){
printf("%d\n",*(arr+i));
}
數(shù)組名是不可改變的赛惩。
int arr1[] = {1,2,3,4,5,6,7,8};
int arr2[] = {1,2,3,4,5,6,7,8};
arr2 = arr1
數(shù)組下標比較易于理解,數(shù)組指針更靈活更高效趁餐。
要點
- 數(shù)組名是數(shù)組第一個元素的地址喷兼。
-
數(shù)組名+下標
表示下標i
元素的地址。 - 數(shù)組名是不可改變的后雷。
2.2 數(shù)組名放入指針
地址存儲在指針中季惯。可以用指針操作地址臀突。
int arr[] = {1,2,3,4,5,6,7,8};
int* p = arr;
for(int i=0;i<8;++i){
printf("%d\n",*(p+i));
}
3. 函數(shù)與數(shù)組
3.1 傳遞數(shù)組給函數(shù)
數(shù)組作為函數(shù)參數(shù)時勉抓,通常必須再用一個參數(shù)傳入數(shù)組大小。
返回值類型 函數(shù)名(類型 參數(shù)名[],int size){
}
或者
返回值類型 函數(shù)名(類型* 參數(shù)名,int size){
}
例如:打印數(shù)組元素
#include <stdio.h>
void PrintArr1(int arr[],int n){
for(int i=0;i<n;++i){
printf("%d ",arr[i]);
}
printf("\n");
}
void PrintArr2(int* arr,int n){
for(int i=0;i<n;++i){
printf("%d ",arr[i]);
}
printf("\n");
}
int main(){
int arr[] = {1,2,3,4,5,6,7,8,9};
PrintArr1(arr,9);
PrintArr1(arr,3);
PrintArr1(arr+6,3);
PrintArr1(arr+3,3);
}
試一下下面代碼
#include <stdio.h>
void Test1(int a[]){
printf("sizeof(a):%d\n",sizeof(a));
printf("a:%p\t&a:%p\n",a,&a);
}
void Test2(int* p){
printf("sizeof(p):%d\n",sizeof(p));
printf("p:%p\t&p:%p\n",p,&p);
}
int main(){
int arr[10];
printf("sizeof(arr):%d\n",sizeof(arr));
printf("arr:%p\t&arr:%p\n",arr,&arr);
Test1(arr);
Test2(arr);
}
數(shù)組作為參數(shù)時候学,數(shù)組退化成指針藕筋,不能利用sizeof
獲取數(shù)組大小,也就不能計算數(shù)組元素個數(shù)盒齿。
- 練習
- 打印數(shù)組所有元素念逞。
- 2062 兩個有序數(shù)組的歸并(歸并中的合并處理)
3.2 從函數(shù)返回數(shù)組
C 語言不允許返回一個完整的數(shù)組作為函數(shù)的參數(shù)困食。通過指定不帶索引的數(shù)組名來返回一個指向數(shù)組的指針。
類型* 函數(shù)名() {
return 數(shù)組名;
}
練習
- 給定數(shù)組隨機填充指定范圍的數(shù)據(jù)翎承。
使用stdlib.h
中的srand(time(NULL))
和rand()
硕盹。 - 將一維數(shù)組的查找
FindArr()
、替換Replace()
封裝成函數(shù)叨咖。
FindArr()
可以返回bool
(有無)瘩例、int
(下標)、int*
(地址)有什么區(qū)別甸各。
- 返回值含義(返回值的含義以及值是人為定義的)
返回值有時存在兩種情況:合法值和非法值垛贤。
如果有非法值的情況,通常使用一些特定的值指代特殊情況趣倾。例如:數(shù)組下標只能是0和正數(shù)聘惦。我們實現(xiàn)數(shù)組查找元素下標時,存在找不到元素的情況儒恋,這時善绎,使用-1
可以作為這種情況的返回值。
重點
int arr[] = {1,2,3,4,5,6};
// sizeof(數(shù)組名)
printf("sizeof(arr) = %ld\n",sizeof(arr));
// 數(shù)組名的值
printf("arr=%p\n&arr[0]=%p\n",arr,&arr[0]);
數(shù)組名是地址诫尽,是常量禀酱。
- 可以使用指針操作:解引用
- 數(shù)組作為函數(shù)參數(shù)和返回值時,傳指針/地址牧嫉。
數(shù)組下標與數(shù)組長度的關(guān)系
-
arr
長度為n
剂跟,最后一個元素的下標為n-1
。 - 下標為
i
是第i+1
個元素酣藻,前面有i
個元素(不包含i
)曹洽,后面有n-(i+1)
個元素(不包含i
)。 - 下標i和j之間有
j-i
個元素(包含i
臊恋,不包含j
)
數(shù)組地址與數(shù)組名的關(guān)系
- 數(shù)組
arr
的首地址為arr
衣洁,下標為i的地址為arr+i
。 - 令
p=arr+i
,那么下標對應(yīng)為p-arr
抖仅。 -
p
前面有p-arr
個元素(不包含p
)坊夫,后面有n-(p-arr+1)
個元素(不包含p
)。
4. 多維數(shù)組
4.1 聲明
- 語法
類型 數(shù)組名[元素個數(shù)1][元素個數(shù)2]...[元素個數(shù)N];
多維數(shù)組最常用形式是二維數(shù)組撤卢。二維數(shù)組相當于一個行列組成的表环凿。
類型 二維數(shù)組名[行數(shù)][列數(shù)];
例如下面是一個4
行3
列元素類型為int
的表。
int days[4][3];
4.2 初始化二維數(shù)組
多維數(shù)組可以通過在括號內(nèi)為每行指定值來進行初始化放吩。
int days[4][3]={
{31,28,31},
{30,31,30},
{31,31,30},
{31,30,31}
};
4.3 訪問二維數(shù)組元素
二維數(shù)組中的元素是通過使用下標(即數(shù)組的行索引和列索引)來訪問的智听。
// 獲取一月份的天數(shù)
int n = days[0][0];
// 修改二月份的天數(shù)
days[0][1] = 29;
// 打印一月份天數(shù)
printf("%d",days[0][0]);
4.4 二維數(shù)組元素遍歷
通常使用嵌套循環(huán)來處理二維數(shù)組。
for (int i = 0; i < 4; i++ ) {
for (int j = 0; j < 3; j++ ) {
printf("a[%d][%d] = %d\n",i,j,a[i][j]);
}
}
4.5 二維數(shù)組輸入
int n,m;
scanf("%d%d",&n,&m);
int arr[n][m];
for (int i=0;i<n;++i){
for (int j=0;j<m;++j){
scanf("%d",&arr[i][j]);
}
}
練習
輸入
m
個學生的n
門課程成績,輸出各門課程成績以及總成績和平均值到推。-
二維數(shù)組通晨既可用于表示數(shù)學中的矩陣。實現(xiàn)矩陣基本運算(加法莉测、減法颜骤、乘法、轉(zhuǎn)置)捣卤。
-
把
m
年n
月的日期忍抽,按星期以日歷方式放入二維數(shù)組(列表示星期),并打印出來董朝。
4.6 簡化
初始化二維數(shù)組可以有如下簡化寫法:
- 省略內(nèi)部嵌套括號鸠项。
int days[4][3]={31,28,31,30,31,30,31,31,30,31,30,31};
- 省略第一維大小,第二維不能省略子姜。
int days[][3]={31,28,31,30,31,30,31,31,30,31,30,31};
問題
二維數(shù)組可以整體初始化嗎祟绊?
練習
4.7 二維數(shù)組作為函數(shù)參數(shù)
二維數(shù)組作為函數(shù)參數(shù),需要同屬輸入行和列的個數(shù)闲询。
void PrintMatrix(int m[4][3],int r,int c)
for (int i = 0; i < r; i++ ) {
for (int j = 0; j < c; j++ ) {
printf("%d\n",m[i][j]);
}
}
4.8 多維數(shù)組
大于二維的數(shù)組的用法與二維數(shù)組一樣久免,只是使用比較少。
int days[][4][3]={
{31,28,31,30,31,30,31,31,30,31,30,31}, // 平年
{31,29,31,30,31,30,31,31,30,31,30,31} // 閏年
};
printf("平年二月天數(shù)為%d\n",days[0][0][1]);// 平年第一季度第二個月
printf("閏年二月天數(shù)為%d\n",days[1][0][1]);// 閏年第一季度第二個月
多維數(shù)組初始化只能第一個維度可以省略扭弧。
5 const
數(shù)組
5.1 const
數(shù)組是什么?
const int arr[]={1,2,3,4,5,};
數(shù)組變量已經(jīng)是const
指針记舆,表示數(shù)組中的每一個元素都是const int
鸽捻,即每個元素不能通過arr
改變。
例如:
const int arr[]={1,2,3,4,5,};
arr[0] = 0;
5.2 const
數(shù)組怎么用泽腮?
保護數(shù)組值
因為數(shù)組作為函數(shù)參數(shù)是以地址方式傳遞的御蒲,所以函數(shù)內(nèi)部可以修改數(shù)組的值。
為了保護數(shù)組不被函數(shù)破壞诊赊,可設(shè)置參數(shù)為const
厚满。
例如:
int sum(const int arr[],int len);
或者
int sum(const int* arr,int len);
6 變量指針 vs 數(shù)組指針
變量指針:指向單個變量的指針。
數(shù)組指針:指向數(shù)組的指針碧磅。
#include <stdio.h>
int main () {
int n = 10;
int *p;
p = &n; // p指針指向變量
printf("*p = %d\n",*p);
int arr[] = {1,2,3,4,5,};
p = arr;// p指針指向數(shù)組
printf("*p = %d\n",*p);
printf("*(p+1) = %d\n",*(p+1));
printf("*(p+2) = %d\n",*(p+2));
printf("*(p+3) = %d\n",*(p+3));
printf("*(p+4) = %d\n",*(p+4));
return 0;
}
指針既可以指向一個基本類型變量又可以指向一個數(shù)組碘箍。所以在使用時要注意分辨。
7 項目
輸入年份打印萬年歷鲸郊。