Linux 核心設計實作摘要
C語言
指標理解
C Traps and Pitfalls 的 “Understanding Declarations”小節提到如何解讀指標。每一個C的變數宣告可以拆成兩個部分。
- 型態
- 一串將會回傳這個型態的表達式
float f, g;
代表f, g將會回傳floatfloat ff();
代表ff()將會回傳float,因此ff是一個function並且會回傳floatfloat *pf;
代表*pf江會回傳float,因此pf是一個pointerfloat *g(), (*h)();
首先()
的優先度大於*
因此*g()
可以改寫成*(g())
,由此可知g是function並且會回傳一個pointer to a float的指標。而(*h)()
代表h是一個pointer to a function指標,而且這個function會回傳float。
知道如何宣告變數後就可以寫出,就可以知道如何寫出這個類型強制轉型的寫法,只需要把變數名稱和分號移除,最後再加上括號float *g();
在這裡的g是一個回傳pointer的function,這個pointer指向float。而g強制轉型的寫法即為(float *())
Byte和Bit
1 Byte = 8 Bits
指標運算符號
Address-of operator
&
稱為 Address-of operatorDereference operator
*
稱為 Dereference operator
將pointer所指向的值給另一個變數(This is called a “load” operation.)1
int bar = *foo_ptr;
將值儲存到pointer所指的位置(This is called a “store” operation.)
1
*foo_ptr = 42; Sets foo to 42
->操作符
定義一個struct foo和一個foo的指針foo_ptr
1 | struct foo { |
如果要查看foo_ptr所指向的內容,可以用
1 | (*foo_ptr).size = new_size; |
或者是用->
操作符
1 | foo_ptr->size = new_size; |
陣列Array
宣告陣列
1 | int array[] = { 45, 67, 89 }; |
在C語言,你宣告了一個陣列array
之後,當你使用的時候,array
這個變數其實是一個指向這個陣列第一個元素的指針,我們把這個行為稱為decaying
,因為陣列被decays
成指針了。不過他還是和針的指針有一點不同,其中就是如果用sizeof(array)
來看陣列的話,回傳的將會是陣列的總長度(在這個範例就是(sizeof(int) = 4) × 3 = 12)而不是單一個指針的長度。
下面這三種狀況對陣列來說都是一樣的
1 | array == &array == &array[0] |
他們分別代表“array”, “pointer to array”, 和 “pointer to the first element of array”,但在C這三個東西是一樣的
陣列++
對於一般變數來說variable += 1
代表對變數+1,但是對於指標來說代表對目前指標的位置加上資料型態的大小。以我們上一個例子來說我們的陣列儲存的是int,而array
被decays成pointer了,所以array + 1
就是加上sizeof(int)
,等同於我們把指針移動到下一個元素。
Indexing
首先看一下以下例子
1 | int array[] = { 45, 67, 89 }; |
這段程式宣告的一個三個元素的陣列array
,還有一個int指針array_ptr
,可以用下面這張圖可以看到array[1]
和array_ptr[0]
指向同一個記憶體。
{: w=”700” h=”200” }
我們可以看到其實[]
是指針的操作符,array[1]
等同於*(array + 1)
參考:
Everything you need to know about pointers in C
https://boredzo.org/pointers/
Linux 核心設計實作摘要