c語言中陣列和指標經常會放在一起講,因為對於陣列遍歷的時候,可以通過指標的移動來代替。所以,陣列和指標的關係有時候會讓人很模糊,甚至讓人混淆。本篇博文將試圖說明陣列的特性,指標的特性,以及陣列和指標的聯絡與區別。
float candy[365], char code[12], int states[50], int powers[8] = 。若使用const關鍵字,則陣列為唯讀陣列,不能被改變。
特殊說明:
float rain[5][12]; 二維陣列,也可以說是有12個float的一維陣列。宣告方式就是指定行和列大小。
若flizeny為一維陣列名,flizny == &flizny[0]成立,說明一維陣列名為陣列首元素的位址。並且,filzny為常量,可以進行加減運算,但不能進行自加或自減(變數才能進行)。但陣列名可以賦值給指標變數,從而指標變數可以進行各種運算操作。
#include#define size 4
int main(void)
return 0;
}
上例中在for迴圈中可以使用陣列名進行代替。由於陣列名即為位址,則可以進行諸如類似指標的運算,如*(arr + 1),取陣列第二個元素。
指標變數和陣列都可以作為函式引數型別。但若在函式中進行陣列的遍歷操作,則應指明陣列長度,如int sum(int * ar, int n)或int sum(int ar, int n),否則產生陣列越界的問題。第二種方式更直觀,一看就知道是陣列操作。
在函式宣告時,以下4種方式都可以。
int sum(int *ar, int n);
int sum(int *, int n);
int sum(int ar, int n);
int sum(int , int);
除了指定遍歷長度,也可以使用頭指標和尾指標的方式:int sump(int * start, int * end);在函式內進行start < end; start++,以避免陣列越界的問題。
獲取指標變數指向位址的值,如*ptr。
獲取指標的位址,如&ptr,若用ptt = &ptr,則ptt為指向指標的指標。
指標+/- integer:指標移位操作。
自增自減操作
兩個指標變數做差值,得到位址差值,然後除以位元組數(相應的資料型別)。
關係運算進行比較。
例項:int * pt; *pt = 5(嚴重錯誤)。原因:將pt指向的位址儲存的值賦值為5,但pt未初始化,只有乙個隨機的值,可能指向記憶體中的任意位置,即有可能覆蓋系統重要資料,造成資料覆蓋,甚至程式崩潰。
int sum(const int ar, int n); 在函式體內不允許通過ar改變陣列內的資料,但實際傳入的函式引數不一定為常量陣列。使用const以保護陣列內的資料不發生改變。
常量可以使用#define定義,但const可以定義諸如常量陣列,常量指標,指標常量等。
double rates[5] = ; const double *pd = rates;
陣列為普通陣列,指標為常量指標,不能通過指標來修改指標指向的內容。*pd = 29.89; // not allowed,pd[2] = 222.22; // not allowed,rates[0] = 99.99; // allowed because rates is not const。
無論是否使用指標表示法或陣列表示法,總是不允許使用pt(常量指標)來改變指標指向的資料的值。
常量資料和非常量資料的位址都可以賦值給常量指標。
double rates[5] = ;
const double locked[4] = ;
const double *pd = rates; // valid
pc = locked; // valid
pc = &rates[3];
然而,只有非常量資料的位址可以賦值給一般指標變數。
double rates[5] = ;
const double locked[4] = ;
double *pnc = rates; // valid
pnc = locked; // not valid
pnc = &rates[3]; // valid
很好理解,如果pnc = locked被允許,那麼可以使用pnc修改常量陣列的值。
const有更多可能的用途。 例如,您可以宣告並初始化指標,以使其無法指向其他位置。
double rates[5] = ;
double * const pc = rates; // pc 指向陣列的首元素位址
pc = &rates[2]; // invalid,不允許指向其他位置
*pc = 92.99 // valid,可以通過指標修改指向的值。
double rates[5] = ;
const double * const pc = rates;
pc = &rate[2]; // invalid
*pc = 92.99; // invalid
說明指標一旦初始化,則指標指向的位址不能改變,同時也不能通過指標修改其指向的值。
int zippo[4][2] = , , , };
資料描述
zippo
the address of the first two-int element
zippo+2
the address of the third two-int element
*(zippo+2)
the third element, a two-int array, hence the address of its first element, an int
*(zippo+2) + 1
the address of the second element of the two-int array, also an int
*(*(zippo+2) + 1)
the value of the second int in the third row(zippo[2][1]
如何宣告乙個指向二維陣列的指標呢?int (* pz)[2]; // pz 指向乙個包含2個int型別的陣列,陣列每個元素為2個int型的陣列。
int * pax[2]; // pax是乙個陣列指標,每個指標均為指向int型。
將乙個指標指定給另乙個指標的規則比數字型別的規則更嚴格。例如,可以將int型別值賦值給double型別的變數,但不能將指向int型的指標變數賦值給指向double型別的指標變數。
int n = 5; double x; int * pl = &n; double *pd = &x; x= n(隱式型別轉換); pd = pl(編譯錯誤,不能轉換);
這些限制擴充套件到更複雜的型別,以下例子可以說明。
int * pt; int (*pa)[3]; int ar1[2][3]; int ar2[3][2]; int *p2(指向指標的指標);
pt = &ar1[0][0]; // both pointer-to-int
pt = ar1[0]; // both pointer-to-int
pt = ar1; // not valid, ar1 is a array of three-int
pa = ar1; // both pointer-to-int[3]
pa = ar2; // not valid, pa is a array of three-int ar2 is a array of two-int
p2 = &pt // both pointer-to-int
p2 = ar2; // not valid, p2 is a pointer-to-int *, ar2 is array of two-int
宣告方式
void sum_row(int ar[cols], int rows);
void sum_cols(int [cols], int);
int sum2d(int (*ar)[cols], int rows);
c99新特性,int sum2d(int rows, int cols, int ar[row][cols]);
int sum2d(int, int, int ar[*][*]);
注意,行和列的int型應該放在陣列引數的前面,使用vla可以靈活使用可變行列的陣列。
指標與陣列,指標陣列 陣列指標
int a 10 print n a p,a p a,a print n a 1 p,a 1 p a 1,a 1 a做乙個指標,步長為4,指向乙個元素,a做乙個指標,步長為40,指向乙個維陣列 int b 3 4 print n b p,b p,b p b,b,b print n b 1 p,b 1...
指標陣列與陣列指標
1.指標陣列 指標陣列中每乙個元素都是乙個指標,也既是存放字串的首位址。所以指標陣列適合處理若干個長度不等的字串。定義的一般形式為 型別說明符 指標陣列名 陣列長度 例如 int p 3 宣告乙個陣列,指標陣列p,由3個int型別指標變數元素組成 從運算子的優先順序分析,由於 的優先順序大於 所以p...
指標陣列與陣列指標
呵呵,實在是厭倦了繞口的解釋。指標陣列,故名思義,就是指標的陣列,陣列的元素是指標 陣列指標,同樣,就是直想陣列的指標。簡單舉例說明 int p 2 首先宣告了乙個陣列,陣列的元素是int型的指標。int p 2 宣告了乙個指標,指向了乙個有兩個int元素的陣列。其實這兩種寫法主要是因為運算子的優先...