定義
數(shù)組就是相同數(shù)據(jù)類型構(gòu)成的一組數(shù)
數(shù)組名
- 數(shù)組名的值是一個指針常量(你不能修改常量的值),它是數(shù)組第一個元素的地址,他的類型取決于數(shù)組元素的類型
- 數(shù)組和指針是不一樣的,數(shù)組具有確定數(shù)量的元素,而指針只是個標(biāo)量值
- 指針常量所指向的是內(nèi)存中數(shù)組的起始位置,如果修改這個指針常量,唯一可行的方法就是把整個數(shù)組移動到內(nèi)存的其他位置
只有在兩種場合下,數(shù)組名并不用指針常量來表示
- 當(dāng)數(shù)組名作為sizeof操作符,sizeof返回整個數(shù)組的長度,而不是指向數(shù)組的指針的長度
- 單目操作符&的操作數(shù)時,取一個數(shù)組名的地址所產(chǎn)生的是一個指向數(shù)組的指針,而不是指向某個指針常量值得指針
這兩者是等價的
int a[10];
int *c;
c = &a[0];
c = a;
初始化
類型標(biāo)識符 + 數(shù)組名 + 數(shù)組元素的個數(shù)(常量表達(dá)式) + 初始值
int arr[5] = {0};
- excess element 超過 數(shù)組越界
數(shù)組元素不要超過給定的,數(shù)組越界有可能導(dǎo)致程序崩潰
中括號中數(shù)組的元素的個數(shù) - 不能放變量
int arr6[4] = {1,2,3,4,5};
int i = 10;
int arr1[i] = {0};
int arr1[8 + 2] = {0};
int arr2[] = {1,2,3};// 不建議
float arr3[3] = {1.0,2.0,3.0};
double arr4[3] = {2.0,3.0,4.023123};
long arr5[4] = {5345,64563,234};
指針 和 下標(biāo)
下標(biāo)
下標(biāo)和數(shù)組名一起使用,用于標(biāo)識該集合中某個特定的值
int b[10];
*(b+3);
b的值是一個指向整型的指針,*(b+3)
所指向的是數(shù)組的第1個元素向后移3個整數(shù)長度的位置,然后間接訪問這個新的位置
除了優(yōu)先級之外,下標(biāo)引用和間接訪問完全相同
array[subscript];
*(array+(subscript));
關(guān)于下標(biāo)和指針的理解
int array[10];
int *ap = array +2;
指針 | 轉(zhuǎn)換 | 下標(biāo) |
---|---|---|
ap | array + 2 | &array[2] |
*ap | *(array + 2) | array[2] |
ap[0] | *(ap+(0)) = array + 2 | &array[2] |
ap+6 | array + 2 + 6 = array + 8 | &array[8] |
*ap+6 | *(array + 2) + 6 | array[2]+6 |
*(ap+6) | *(array 2 + 6) | array[8] |
ap[6] | *(ap+(6)) | &array[8] |
&ap | ap指針?biāo)诘牡刂?/td> | 無 |
ap[-1] | *(array+(-1)) | array[1] |
2[array]
相當(dāng)于*(2+(array))
也就是說*(array+2)
- 有些編譯器會有下標(biāo)檢查,但這是一個不小的負(fù)擔(dān),不過對于如今的電腦而言,并不是個大的問題
- 指針有時候會比下標(biāo)更有效率,但不應(yīng)因為效率而影響程序的可讀性
一般有數(shù)組的地方就有循環(huán)
遍歷一個數(shù)組 數(shù)組下標(biāo),從0開始到 數(shù)組元素個數(shù)-1 為止
for (int i = 0 ; i < 3; i++) {
printf("%d\n",arr2[i]);
}
數(shù)組 和 指針
- 聲明一個數(shù)組時,編譯器將根據(jù)聲明所指定的元素數(shù)量為數(shù)組元素保留內(nèi)存空間,然后在創(chuàng)建數(shù)組名,它的值是一個常量,指向這段空間的起始位置.
- 聲明一個指針變量時,編譯器只為指針變量保存內(nèi)存空間,如果它是一個自動變量,它甚至根本不會被初始化
int a[5];
int *b;
上述聲明后
- 表達(dá)式
*a
是完全合法的,但表達(dá)式*b
是非法的 -
*b
將訪問內(nèi)存中某個不確定的位置,或者導(dǎo)致程序終止 -
b++
能通過編譯,但a++
卻不能,因為a的值是一個常量
作為函數(shù)參數(shù)的數(shù)組名
當(dāng)數(shù)組名作為參數(shù)傳遞給函數(shù)時是指向數(shù)組第一個元素指針的拷貝,函數(shù)如果執(zhí)行了下標(biāo)引用,實(shí)際上是對這個指針執(zhí)行間接訪問操作,函數(shù)可以訪問和修改調(diào)用程序的數(shù)組元素
以下兩個聲明只是在當(dāng)前這個上下文環(huán)境中相等
int fun(char *string);
int fun(char string[]);
字符數(shù)組 和 字符串
字符數(shù)組
char arr[4] = {'a','n','s','d'};
char arr[4] = "ansd";
以下聲明,盡管第二個聲明看像去是一個字符串常量,實(shí)際上并不是
char message[] = "Hello";
char *message2 = "Hello";
以上聲明
- 前者初始化一個字符數(shù)組的元素
- 后者是一個真正的字符串常量,這個指針變量被初始化為指向這個字符串常量的存儲位置
輸出方法
for (int i = 0; i < 4; i++) {
printf("%d\t",arr[i]);
printf("%c\t\n",arr[i]);
}
多維數(shù)組
初始化
// 方法一
int matrix[2][3] = {100,101,102,110,111,112};
// 方法二
matric[0][2] = 102;
// 方法三
int matix2[3][5]={
{00,01,02,03,04},
{10,11,12,13,14},
{20,21,22,23,24}
}
存儲順序
int a[12];
int b[3][4];
int c[2][2][3];
數(shù)值 | int a[12]; |
int b[3][4]; |
int c[2][2][3]; |
---|---|---|---|
0 | a[0] | b[0][0] | c[0][0][0] |
1 | a[1] | b[0][1] | c[0][0][1] |
2 | a[2] | b[0][2] | c[0][0][2] |
3 | a[3] | b[0][3] | c[0][1][0] |
4 | a[4] | b[1][0] | c[0][1][1] |
5 | a[5] | b[1][1] | c[0][1][2] |
6 | a[6] | b[1][2] | c[1][0][0] |
7 | a[7] | b[1][3] | c[1][0][1] |
8 | a[8] | b[2][0] | c[1][0][2] |
9 | a[9] | b[2][1] | c[1][1][0] |
10 | a[10] | b[2][2] | c[1][1][1] |
11 | a[11] | b[2][3] | c[1][1][2] |
// 給數(shù)組a賦值
int *d = a;
for (int i = 0; i < 12; i++)
{
*d = i;
d++;
}
// 給數(shù)組b賦值
d = &b[0][0];
for (int i = 0; i < 12; i++)
{
*d = i;
d++;
}
// 給數(shù)組c賦值
d = **C;
for (int i = 0; i < 12; i++)
{
*d = i;
d++;
}
// 打印數(shù)組a
for (int i = 0; i < 12; i++)
{
cout << "a"<<i<<"="<<a[i] << endl;
// printf("a[%d] = %d \n", i,a[i]);
}
// 打印數(shù)組b
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
cout << "b" << i << j <<"=" << b[i][j] << endl;
}
}
// 打印數(shù)組c
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
for (int k = 0; k < 3; k++)
{
cout << "c" <<i<<j<<k<<"=" <<c[i][j][k] << endl;
}
}
}
數(shù)組名
- 一維數(shù)組名得值是一個指針常量,類型:指向元素類型的指針,它指向數(shù)組的1個元素
- 二維數(shù)組名的值是一個指向一個包含x個某類型元素的數(shù)組的指針
int matrix[2][3];
-
matrix;
類型:指向包含3個整形元素的數(shù)組的指針 -
*matrix;
類型:指向整形的指針
下標(biāo)
array[s2][s1];
*(*(array+(s1))+(s2));
注意:
array[3,4];
相當(dāng)于
array[4];
逗號操作符首先對第1個表達(dá)式求值,但隨即丟棄這個值,最后的結(jié)果是第2個表達(dá)式的值
指向數(shù)組的指針
對于一維數(shù)組,以下聲明是合法的
int vector[10],*vp = vector;
但對于多維數(shù)組,以下聲明則是非法的
int matrix[3][10],*mp = matrix;
因為matrix并不是一個指向整形的指針,而是一個指向整形數(shù)組的指針,其指針聲明如下
int (*)p[10];
下標(biāo)的引用的優(yōu)先級高于間接訪問,但由于括號的存在,首先執(zhí)行的還是間接訪問,接下來執(zhí)行的是下標(biāo)引用,所以p指向的是某種類型的數(shù)組,對該數(shù)組進(jìn)行下標(biāo)引用操作得到的是一個整型值,所以p是一個指向整型數(shù)組的指針
int (*p)[10] = matrix;
它使p指向matrix的第一行,p是一個指向擁有10個整形元素的數(shù)組指針
如果需要一個指針逐個訪問整型元素可以進(jìn)行如下聲明
int *pi = &matrix[0][0];
int *pi = matrix[0];
作為參數(shù)的多維數(shù)組
其實(shí)際傳遞的是指向數(shù)組第一個元素的指針,多維數(shù)組的每個元素本身是另外一個數(shù)組,編譯器需要知道它的維數(shù),以便為函數(shù)形參的下標(biāo)表達(dá)式求值
int matrix[3][10];
fun(matrix);
參數(shù)matrix的類型是指向包含10個整形元素的數(shù)組的指針
fun的函數(shù)原型如下
void fun(int (*mat)[10]);
void fun(int mat[][10]);
數(shù)組長度自動計算
對于多維數(shù)組,只有第一維才能根據(jù)初始化列表缺省地提供,其他幾個維度必須顯式地寫出
指針數(shù)組
int *api[10];
- 下標(biāo)引用高于間接訪問,所以在這個表達(dá)式中,首先執(zhí)行下標(biāo)引用,因此api是某類型的數(shù)組,其元素個數(shù)為10
- 隨后進(jìn)行間接訪問操作,得到一個整形,所以其元素類型為指向整形的指針
例:
以下為一個指針數(shù)組
char const keyword[]={
"do",
"for",
"if",
"register",
"return";
"switch"
"while"
};
#define N_KEYWORD (sizeof(keyword)/sizeof(keyword[0]))
以下則為一個矩陣
char const keyword[][9]={
"do",
"for",
"if",
"register",
"return";
"switch"
"while"
};
sizeof用于對數(shù)組中的元素進(jìn)行自動計數(shù)
- 通過sizeof來得到數(shù)組中元素的個數(shù)
- sizeof(keyword)的結(jié)果為整個數(shù)組所占用的字節(jié)數(shù)
- sizeof(keyword[0])為數(shù)組每個元素所占用的字節(jié)數(shù)
- 這兩個數(shù)相除為整個數(shù)組的個數(shù)
sizeof是字符的大小
int a[] = {1,2,3,4,5};
sizeof(a) / sizeof(int) 數(shù)據(jù)大小 / 數(shù)據(jù)類型大小 = 多少個
數(shù)組:排序 冒泡排序
冒泡排序是一個雙層的for循環(huán) ,外層循環(huán)控制的是比較的趟數(shù),內(nèi)層循環(huán)控制的是每次比較的次數(shù)
int arr6[5] = {6,5,4,3,1};
for(int i = 0; i < 5 - 1; i++) {
for(intj = 0; j < 5 - i - 1; j++) {
if(arr6[j] > arr6[j+1]) {
arr6[j] = arr6[j] ^ arr6[j+1];
arr6[j+1] = arr6[j] ^ arr6[j+1];
arr6[j] = arr6[j] ^ arr6[j+1];
}
}
}
for(int i = 0; i < 5; i++) {
printf("arry5[%d] is %d\n",i,arr6[i]);
}