#include <stdio.h>
#define SIZE 50
int main(void)
{
int counter, evens[SIZE];
for (counter = 0; counter < SIZE; counter++)
even[counter] = 2 * counter;
}
使用陣列時防之下標超出邊界,使用越界下標可能會導致程式改變其它 變數的值
7、指定陣列的大小
宣告陣列時只能在方括號中使用整型常數表達式。下標必須大於0,陣列大小必須大於0,陣列大小必須是整數。
#include <stdio.h>
#define MONTHS 12 //一年的月份
#define YEARS 5 //年數
const float rain[YEARS][MONTHS]={{},{},{}, };
int year,month;
float subtot, total;
for (year = 0, total = 0; year < YEARS; year++)
{ //處理每一年的數據
for (month = 0, subtot = 0; month < MONTHS; month++)
//處理每月的數據
subtot += rain[year][month];//處理每一年的的數據
printf("%5d %1.51f\n", 2010 + year, subtot);
total += subtot;
}
巢狀for回圈的內層回圈,在年不變的情況下,計算這年的總降水量;而外層回圈改變year的值,重複遍歷month,計算5年總降水量。
2、初始化二維陣列
const float rain[YEARS][MONTHS]=
{ {},
{},
{}
};
可以省略內部花括號,只保留最外面一對花括號。但是如果初始化值不夠,則按先後順序逐行初始化,直至用完全,後面沒有初始化的元素被同一初始化爲0.
3、其它多維陣列
一維陣列想象成一行數據,二維陣列想象成數值表,三維陣列是一疊數據表。或者看作陣列的陣列。多次巢狀。
short dates[SIZES];
short * pti;
pti = dates;
地址按位元組編址,short佔兩個位元組。
指針加1指的是增加一個儲存單元。
對陣列來說,加1後的地址是下一個元素的地址。
這也是爲什麼要宣告指針所指向物件型別的原因之一。
指針的值是它所指向物件的地址。在指針前使用*運算子可以得到該指針所指向物件的值。指針加1,指針的值遞增它所指向型別的大小。
`dates + 2 ==&date[2];//地址相同
*(dates + 2)== dates[2];//值相同`
到記憶體的ar位置,然後移動n個單元,檢索儲存在那裏的值。
間接運算子(*)優先順序高於+
int sum (int * ar)
{
int i;
int total = 0;
for (i = 0; i < 10; i++) //假設陣列有十個元素
total += ar[i]; //ar[i]與*(ar + i)相同
return total;
}
2)把陣列元素的個數作爲第二個參數
int sum(int * ar, int n)
{
int i;
int total = 0;
for (i = 0; i < n; i++) //假設陣列有n個元素
total += ar[i]; //ar[i]與*(ar + i)相同
return total;
}
只有在函數原形或定義頭中,纔可以用 int ar[ ] 替代 int *ar.int ar[ ] 和 int *ar,都表示ar是一個指向 int 的指針。 int *ar只能用於宣告形式參數。int ar[ ]提醒讀者指針ar指向的不僅是一個int型別值,還是一個int型別陣列的元素。
函數原型可以省略參數名,函數定義中不能省略參數名
1、使用指針形參
函數處理陣列必須要知道何時開始、何時結束。
1)用一個指針形參標識陣列的開始,用一個整數形參表明待處理陣列的元素個數。
2)傳遞兩個指針,一個開始一個結束。
int sump(int * start, int * end)
{
int total = 0;
while (start < end)
{
total += *start;
start++;//指針變數纔可以用++,是變數才行。陣列表示的是常數。
}
return total;
}
end 所指向的實際位置上在陣列最後一個元素的後面。陣列後面第一個位置的指針仍是有效的指針。
難點:total += *start++
*start++; ++start
一元運算子和++運算子相同,++在前,從右到左,先遞增指針,再使用。
++在後,先使用,後遞增。
原因:start++作爲一個整體與 * 運算,++後綴的++的運算規則其實是先運算,再加1。
指針操作
該指針指向的地址,儲存在指針指向地址上的值,指針自己的地址。
指針剛宣告完畢時,它並無指向的地址,只有當與某儲存的變數發生關係時,纔有指向地址。
比較:前提是兩個指針都指向相同類型的物件。
1)使用一個指針去減另一個指針,得到一個整數,
2)用一個指針減一個整數得到一個指針
保護陣列中的數據
只有程式需要在函數中改變該數值時,纔會傳遞指針。對於數組別無選擇,必須傳遞指針,因爲這樣效率高。如果一個函數按值傳遞陣列,則必須分配足夠的空間來儲存原陣列的副本,然後把原陣列所有的數據拷貝至新的陣列中。把陣列的地址傳遞給函數,然函數直接處理原陣列效率更高。
1、對形式參數使用const
int sum(const int ar[ ], int n);//int ar[ ]和int *ar都表示指向int的指針
const並不要求原陣列是常數,而是該函數在處理陣列時將其視爲常數,不可更改。需要修改陣列,在宣告中不使用const。
2、可以建立const陣列、指針、和指向const的指針。
const int day [SIZES] = { 2, 3, 4, 5 };
const double * pd = rates;
doublel * const pc = rates;
7.指針和多維陣列
int zippo[4][2];
zippo 是該陣列元素的地址。所以zippo的值和&zippo[0]的值相同。zippo[0]又是一個內含兩個整數的陣列。所以zippo[0]的值和它首元素(一個整數)的地址相同 &zippo[0][0]。
給指針加一,會增加對應型別大小的數值。zippo佔用兩個int大小,zippo[0]佔用一個int大小。
解除參照一個指針。*(zippo[0]) == zippo[0][0]
*zippo == zippo[0] == &zippo[0][0]
**zippo == *&zippo[0][0]
1、指向多維陣列的指針
int sum2d(int rows, int cols, int ar[rows][cols]);
可以省略原形中的形參
int sum2d(int, int, int ar[*][*]);