參考資料:
高教版《全國計算機等級考試二級教程——C語言程序設(shè)計》
《21天學通C語言》
數(shù)組的基本概念
數(shù)組是一組帶索引的數(shù)據(jù)存儲位置碧绞,各位置的名稱相同冷冗,以不同的下標或索引來區(qū)分催跪。下標(也叫作索引)指的是數(shù)組變量名后面方括號中的數(shù)字。數(shù)組中的每個存儲位置被稱為數(shù)組元素夷野。
與其他C語言的變量類似懊蒸,在使用數(shù)組前必須聲明它。
一維數(shù)組的定義和一維數(shù)組元素的引用
一維數(shù)組的定義
當數(shù)組中的每個元素只帶有一個下標時悯搔,稱這樣的數(shù)組為一維數(shù)組骑丸。
在C語言中,定義一維數(shù)組的語句一般形式如下:
類型名 數(shù)組名[整型常量表達式],……妒貌;
例如:
int a[8];
在這里通危,int是類型名,a[8]就是一維數(shù)組說明符灌曙。
以上語句說明了以下幾點:
- 定義了一個名為a的一維數(shù)組菊碟。
- 方括號中的8規(guī)定了a數(shù)組含有8個元素,它們是a[0],a[1],a[2]……
- 類型名int規(guī)定了a數(shù)組中每個元素都是整型在刺,在每個元素中只能存放整型數(shù)逆害。
- 每個元素只有一個下標。每個數(shù)組中第一個元素的下標總為0(稱為數(shù)組下標的下界)蚣驼,因此魄幕,以上a數(shù)組中的最后一個元素的下標是7(稱為數(shù)組下標的上界)。
- C編譯程序?qū)閍數(shù)組在內(nèi)存中開辟名為a[0]-a[7]的8個連續(xù)的存儲單元颖杏,可以用這些名字來直接引用各存儲單元纯陨。
在一個定義數(shù)組的語句中,可以有多個數(shù)組說明符留储,它們之間用逗號隔開翼抠,如:
double w[22], v[100], u[5];
數(shù)組說明符和普通變量名可同時出現(xiàn)在一個類型定義語句中,如:
char c1, c2, carr[81];
注意:數(shù)組說明符的一對方括號中只能是整型常量或整型常量表達式获讳。
聲明數(shù)組時机久,可以用字面常量或通過#define創(chuàng)建的符號常量來指定元素的個數(shù),因此以下兩種聲明方式等價:
#define MONTHS 12
int array[MONTHS];
int array[12];
注意:大部分編輯器都不允許用const關(guān)鍵字創(chuàng)建的符號常量來聲明數(shù)組的元素赔嚎。
以下語句在編譯時會報錯:
const int MONTHS = 12;
int array[MONTHS];
一維數(shù)組元素的引用
一維數(shù)組的引用形式如下:
數(shù)組名 [下標表達式]
例如膘盖,若有以下定義語句:
double x[8];
則x[0],x[j]尤误,x[i + k]都是對x數(shù)組中元素的合法引用形式侠畔。
- 一個數(shù)組元素實質(zhì)上就是一個變量名,代表內(nèi)存中的一個存儲單元损晤。
- 一個數(shù)組占有一串連續(xù)的存儲單元软棺。
- 在C語言中,一個數(shù)組不能整體引用尤勋。數(shù)組名中存放的是一個地址常量喘落,它代表整個數(shù)組的首地址茵宪。
一維數(shù)組的初始化
一維數(shù)組初始化的形式為:
int a[8] = {0,1,2,3,4,5,6,7};
以上語句給a[0]賦初值0,給a[1]賦初值1……給a[7]賦初值7瘦棋。
當所賦初值少于所定義數(shù)組元素的個數(shù)時稀火,將自動給后面的元素補以初值0。
對于字符型數(shù)組也同樣補以初值0赌朋。例如凰狞,以下兩個定義相等:
char c[5] = {'@'};
char c[5] = {'@', '\0', '\0', '\0', '\0'};
當所賦初值多與所定義數(shù)組元素的個數(shù)時,在編譯時會報錯沛慢。
通過賦初值定義數(shù)組的大小
C語言規(guī)定可以通過賦初值來定義數(shù)組的大小赡若,這時數(shù)組說明符的一對方括號中可以不指定數(shù)組的大小祟敛。例如该窗,以下兩條語句等價:
int a[] = {0, 0, 0, 0, 0};
int a[5] = {0};
一維數(shù)組的使用
數(shù)組元素可用于程序中任何相同類型的非數(shù)組變量的地方秕重,通過使用數(shù)組名和帶方括號的數(shù)組下標來訪問數(shù)組中的各元素诸典。
例如望侈,以下語句將89.95存儲在第2個數(shù)組元素中:
expenses[1] = 89.95;
下面的語句將數(shù)組元素expenses[11]中存儲的值的副本賦給expenses[10]數(shù)組元素:
expenses[10] = expenses[11];
程序中經(jīng)常會將整型變量或表達式作為下標搂蜓,或者甚至是另一個數(shù)組元素漏策,例如:
float expenses[100];
int a[10];
//其他語句已省略
expenses[i] = 100; //i是一個整型變量
expenses[2 + 3] = 100; //expenses[2 + 3]相當于expenses[5]
expenses[a[2]] = 100; //a[]是一個數(shù)組
如果有一個整型數(shù)組a[]胁镐,其中元素a[2]中存儲8圾另,則以下兩種寫法的效果相同:
expenses[a[2]] = 100;
expenses[8] = 100;
一維數(shù)組和指針
一維數(shù)組和數(shù)組元素的地址
在C語言中霸株,在函數(shù)體中或在函數(shù)外部定義的數(shù)組名可以認為是一個存放地址值的指針變量名,其中的地址值是數(shù)組第一個元素的地址集乔,定義數(shù)組時的類型即是此指針變量的基類型去件,數(shù)組名是指向數(shù)組第一個元素的指針。
注意:這個指針變量中的地址值不可改變扰路,也就是說不可以給數(shù)組名重新賦值尤溜,可以認為數(shù)組名是一個地址常量。
比如汗唱,定義:
float a[10], *p, x;
語句a = &x;或a++都是非法的宫莱,因為不能給a重新賦地址值。a將永遠指向數(shù)組的首地址哩罪。
但是授霸,可以聲明一個指針變量并將其初始化以指向該數(shù)組。例如际插,下面的代碼聲明并初始化指針變量p_array碘耳,把array數(shù)組首元素的地址存儲在p_array中:
int array[100];
int *p_array = array;
//其他代碼已省略
因為p_array是一個指針變量,所以可以修改它的值讓它指向別處框弛,或指向array[]的其他元素辛辨。
可以用對數(shù)組名加一個整數(shù)的辦法,來依次表達該數(shù)組中不同元素的地址。例如:
int k;
for(k = 0; k < 10; k++)
p = a + k;
在循環(huán)中并沒有改變a的值斗搞,但通過表達式a+k指攒,逐一給出了a數(shù)組中每個元素的地址,使p依次指向a數(shù)組中的每一個元素僻焚。
可以通過以下循環(huán)從終端讀入數(shù)據(jù)依次放入a數(shù)組中:
for(k = 0; k <10; k++)
scanf("%d", a + k);
語句p = &a[0]和p = a都是合法的允悦。這兩條語句都使指針變量p指向數(shù)組a的首地址。
以下循環(huán)語句中溅呢,由于在進入循環(huán)時使指針變量p指向了a數(shù)組的首地址,p++將使指針變量p依次指向a數(shù)組中的每一個元素:
for(p = a, k = 0; k < 10; k++)
p++;
下面的兩條循環(huán)語句也可以從終端讀入數(shù)據(jù)依次放入a數(shù)組中猿挚,這種操作在一些簡單的OJ題目中比較常見:
for(p = a, k = 0; k < 10; k++)
scanf("%d", p++);
for(p = a; p - a < 10; p++)
scanf("%d", p);
例:
以下程序通過聲明short咐旧、float、double類型的數(shù)組并且依次顯示數(shù)組元素的地址绩蜻,演示了不同類型數(shù)組的元素和地址之間的關(guān)系铣墨。
#include <stdio.h>
//聲明一個計數(shù)器變量和三個數(shù)組
int chr;
short array_s[10];
float array_f[10];
double array_d[10];
int main(void)
{
//打印表頭
printf("\t\tShort\t\tFloat\t\tDouble");
printf("\n============================================================");
//打印各數(shù)組元素的地址
for(ctr = 0; ctf < 10; ctr++)
printf("\nElement %d:\t%ld\t%ld\t%ld", ctr, &array_s[ctr], &array_f[ctr], &array_d[ctr]);
printf("\n============================================================");
return 0;
}
輸出:
Short Float Double
============================================================
Element 0: 13084064 13084000 13083904
Element 1: 13084066 13084004 13083912
Element 2: 13084068 13084008 13083920
Element 3: 13084070 13084012 13083928
Element 4: 13084072 13084016 13083936
Element 5: 13084074 13084020 13083944
Element 6: 13084076 13084024 13083952
Element 7: 13084078 13084028 13083960
Element 8: 13084080 13084032 13083968
Element 9: 13084082 13084036 13083976
============================================================
可以看出,相鄰兩個short類型的元素的間隔是2字節(jié)办绝,相鄰兩個float類型的元素的間隔是4字節(jié)伊约,相鄰兩個double類型的元素的間隔是8字節(jié)。
通過數(shù)組的首地址引用數(shù)組元素
a是a數(shù)組元素的首地址孕蝉,a的值等于&a[0]屡律,則a + 1的值等于&a[1]……a+9的值等于&a[9]。
可以通過間接訪問運算符“*”來引用地址所在的存儲單元降淮,因此對于數(shù)組元素a[0]超埋,可以用表達式*&a[0]來引用,也可以用*(a + 0)或*a來引用佳鳖。
因此霍殴,可以通過以下語句逐個輸出a中數(shù)組元素的值:
for(k = 0; k < 10; k++)
printf("%4d", *(a + k));
此語句與以下語句等效:
for(k = 0; k < 10; k++)
printf("%4d", a[k]);
通過指針引用一維數(shù)組元素
若有:
float a[10], *p, k;
p = a; //或p = &a[0];
可以使用間接訪問運算符,通過指針p來引用a數(shù)組中的元素系吩。
對于數(shù)組元素a[0]来庭,可以用表達式*(p + 0),即*p來引用穿挨;同理月弛,對于數(shù)組元素a[1],可以用表達式*(p + 1)來引用科盛。
因此尊搬,可以通過以下語句逐個輸出a數(shù)組元素的值:
for(p = a, k = 0; k < 10; k++)
printf("%4d", *(p + k));
以上語句與以下語句等效:
for(k = 0; k < 0; k++)
printf("%4d", a[k]);
以上兩種寫法都沒有移動指針p⊥晾裕可以用以下兩種方式逐步移動指針p來引用a數(shù)組中的每一個元素佛寿,逐個輸出a數(shù)組元素的值:
for(p = a, k = 0; k < 10; k++)
printf("%4d", *p++);
for(p = a; p - a < 10; p ++)
printf("%4d", *p);
用帶下標的指針變量來引用一維數(shù)組元素
若有:
int *p, s[10], i; //0≤i<10
p = s;
已經(jīng)知道:
- 可以用&s[i]、s + i和p + i來表示s[i]的地址
- 可以用s[i]、*(s + i)冀泻、*(p + i)來表示數(shù)組元素s[i]
所以常侣,*(p + i)也可以用p[i]來表示。
事實上弹渔,在C語言中胳施,方括號是一種運算符。
因此肢专,當p指向s數(shù)組的首地址時舞肆,表示數(shù)組元素s[i]的表達方式有:
- s[ i ]
- *(s + i)
- *(p + i)
- p[ i ]
注意:s是不可變的,p中的地址是可變的博杖。
函數(shù)之間對一維數(shù)組和數(shù)組元素的引用
數(shù)組元素作為實參
調(diào)用函數(shù)時椿胯,數(shù)組元素可以作為實參傳遞給形參,每個數(shù)組元素實際上代表內(nèi)存中的一個存儲單元剃根,所以對于的形參必須是類型相同的變量哩盲。
數(shù)組名作為實參
數(shù)組名也可以作為實參傳遞,但數(shù)組名本身是一個地址值狈醉,所以對應(yīng)的形參就應(yīng)當是一個指針變量廉油,其基類型必須與數(shù)組的類型一致。
在函數(shù)中苗傅,可以通過此指針變量來引用調(diào)用函數(shù)中對應(yīng)的數(shù)組元素抒线,從而對調(diào)用函數(shù)中對應(yīng)的數(shù)組元素進行操作二改變其中的值。
例1(高教版《全國計算機等級考試二級教程——C語言程序設(shè)計》P117 例9.2):
編寫程序渣慕,通過一個函數(shù)給主函數(shù)中定義的數(shù)組輸入若干大于或等于0的整數(shù)十兢,用負數(shù)作為輸入結(jié)束的標志;調(diào)用另一個函數(shù)輸出該數(shù)組中的數(shù)據(jù)摇庙。
#include <stdio.h>
#define M 100
void arrout(int *, int); //函數(shù)說明語句旱物,此函數(shù)用以輸出數(shù)組中的值
int arrin(int *); //函數(shù)說明語句,此函數(shù)用以給數(shù)組輸入數(shù)據(jù)
int main(void)
{
int s[M], k;
k = arrin(s);
arrout(s, k);
return 0;
}
int arrin(int *a)
{
int i = 0, x;
scanf("%d", &x);
while(x >= 0)
{
*(a + 1) = x;
i++;
scanf("%d", &x);
}
return i;
}
void arrout(int *a, int n)
{
int i;
for(i = 0; i < n; i++)
printf(((i + 1) % 5 == 0) ? "%4d\n" : *(a + 1)); //根據(jù)i的值來確定不同的格式串
printf("\n");
}
當數(shù)組名作為實參時卫袒,對應(yīng)的形參除了是指針外宵呛,還可以有其他形式。上例中arrin函數(shù)的首部還可以寫成以下形式:
int arrin(int a[])
int arrin(int a[M])
此外夕凝,通過指針引用數(shù)組元素時宝穗,除了可以用上例的*(a + i)外,也可以寫出a[ i ]的形式码秉。
數(shù)組元素地址作為實參
當用數(shù)組元素地址作為實參時逮矛,對應(yīng)的形參也應(yīng)當是基類型相同的指針變量。
例2(高教版《全國計算機等級考試二級教程——C語言程序設(shè)計》P119 例9.3):
編寫函數(shù)转砖,對具有10個元素的char類型數(shù)組须鼎,從下標為4的元素開始鲸伴,全部設(shè)置星號“*”,保持前四個元素的內(nèi)容不變晋控。
#include <stdio.h>
#define M 10
#define B 4
void setstar(char *, int);
void arrout(char *, int);
int main(void)
{
char c[M] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'};
setstar(&c[4], M - B);
arrout(c, M);
return 0;
}
void setstar(char *a, int n)
{
int i;
for(i = 0; i < n; i++)
*(a + i) = '*';
}
void arrout(char *a, int n)
{
int i;
for(i = 0; i < n; i++)
printf("%c", a[i]);
printf("\n");
}
輸出:
ABCD******
setstar函數(shù)的首部還可以寫成以下形式:
void setstar(int a[], int n)
void setstar(int a[M - B], int n)