K&R2心得//指標與陣列(上)

翻譯問題:
記憶體→記憶體標的物(贅詞)
P.5-18(疑似筆誤)對指標做其它運算都不合規定→對指標做其它計算都是不合法的→對指數做其它計算都是不合法的
字元→字符
(疑似筆誤)
因此雙引號字元(其實算是一個字的字串)比字元數目實際佔用記憶體空間多1個位置
因此字符實際佔用 比雙引號字符數目多1個位置
使用→參用(參考使用 ?)
P.5-19(筆誤)一開始被設定成指向該字串,但以後隨時可以改成指向別的字串,但如果你企圖更改該字串的內含則結果是無定義的
這是啥?內容?



int *ptr;    int c;
ptr = &c;    =    *ptr = c;



指標:
優點:可使程式清晰而簡潔(下面會証明給你看)
缺點:使程式難易不易懂(但是和上面衝突!XD)
(goto()有相同的缺點)

ANSI C規定:(舊的C不是這樣)
void* 通用指標
char* 字串字標

取址運算(&)
只能用於變數、陣列元素(記憶體)
不能用於暫存器、常數、運算式

間接取值(*)

P.5-4
C的精神是宣造成什麼樣子,用起來就是那個樣子。

指標位址運算
*ptr += 1;    =    *ptr++;    =    *++ptr;    ≠    ++*ptr;
單元運算子是由右向左做的

指標與函數的引數
呼叫函數時,使用指標當作引數可以直接存取或改變原程式段裡的變數,而非副本。

指標與陣列
名詞定義:int a[10];   //[10]叫陣列註標
int a[10];
int *ptr;
ptr = &a[0];    ptr  = a;
*(ptr+1) = &a[1];

事實上,C在遇到a[i]時就將其轉成*(a+i)

a[i] = *(a+i);
&a[i] = &*(a+i) = a+i;

指標和陣列
不同的地方
指標是變數,所以 ptr = aptr++ 是對的。
陣列不是變數,a = ptr a++
a已經有固定的位址,無法改變,而a[i++]才是對的)

宣告
函數宣告時
function( char c[]);    =    function(char *s);
陣列名稱視為參數時,建議使用後者

呼叫
呼叫函數時
f(&a[2]);    =    f(a+2);
a[2]  →字元
&a[2]  →位址
a   →位址
a+2  →位址


位址計算
int *ptr1; ptr = 0;  //初值給0,不指向任何位址。
int *ptr2; ptr2 = ptr1;  //初值給位址,指向指定位址。
C保證0不是任何資料型態的指標。

指標的計算(位址的計算)
int *p;
int *q;
1. 若p與q指向同一個陣列,可做 = = 和 != 的比較,和其它關係運算。
 若p與q指向不同個陣列,只可做 = = 和 != 的比較,其它運算無意義。
2. 指標可以加或減一個整數。
p所指的元數往後算n個元位的位址,C會自動將n乘上每個元素的大小(宣告時決定這個資料型態大小)
3. 若p與q指向同一個陣列,指標相減也是對的。
 <stddef.h>定義ptrdiff_t足夠放入兩指標的差值,差值的資料型態定義為size_t(unsigned int)
4. 指標進行計算時,指標的資料型態要一致。
5.不合規定的計算:相加、相乘、相除

字元的指標與函數
(畫圖比較容易懂)

char m_message[];       char* p_message;
陣列有儲存空間,可以無法逐字修改。
指標則只能指向另一個空間,無法逐字修改。

字串複製
char m_messageA[];
char m_messageB[];
strcpy(m_messageA, m_messageB);  //抄寫字串,不同的記憶體位址(空間)

char* p_messageA;
char* p_messageB;
p_messageA = p_messageB;  //傳遞位址,相同的記憶體空間(若是區域變數,將會消失)

指標陣列;指向指標的指標
指標 可視為字串,排序字串,就可以用這個方式實現。
(畫圖比較容易懂)

多維陣列
daytab[L][W++](L:line, W:word)連續記憶體空間是word
int daytab[10][20];
宣告成 daytab[2][13];    可以用這種方式使用(定址)    daytab[][13];    =    *daytab[13];
             ≠
宣告成 *daytab[13];    =    daytab[][13];

指標初始值
char* name[] = {"英文", "a...", "b...", "c..", "d.."};    //依初始值的數量多少決定元素的數量
在此強調的技巧是,將name[0]浪費掉,從name[1]使用,可以在運算過程容易讀code,比較自然。

指標與多維陣列
int a[10][20];      //可容納10筆字串,每串20個字。
int *b[10];          //可容納10筆字串,每串不限字數。

講到這裡,是不是已經覺得字很模糊?
開始意識不清楚了

陣列:宣告連續的記憶體空間。
指標:指向一個記憶體空間,後續連續的記憶體可以使用。

宣告方式各自不同
1. int a[10];   //連續10筆的記憶體空間,單位大小為int
2. int *a;         //1筆記錄位址的記憶體空間,位址後續記憶體空間可從這裡開始使用,單位大小為int
3. int a[2][10];  //連續2串,每串10筆記憶體空間,20筆位址連續,單位大小為int。
4. int *a[10];    //連續10筆記錄位址的記憶體空間,各自的位址不連續,位址各自後續記憶體空間可從這裡開始使用,單位大小為int。

使用方式,卻有些相通(同上述宣告的1.2.3.4.)
使用方式=計算位址的敘述
1.    a[i];    a+i;
2.    a+i;
3.    a[1][i];    *a[i];    a[][i];
4.    *a[i];    a[][i];

(我也快搞混了)只要注意自己要表達的「意義」,而不是用什麼符號表達什麼。
使用陣列定義陣列,還是指標定位陣列,還是使用指標定位指標,絕對不是使用陣列定義指標。

沒有留言:

張貼留言

(什麼是留言欄訊息?)