# 你所不知道的C語言:指標篇筆記 ### object * object in c: 在執行時期資料儲存的區域,可以明確表示數值內容 C99 [6.2.4] Storage durations of objects * An object has a storage duration that determines its lifetime. There are three storage durations: static, automatic, and allocated. ### C99 [6.5.3.2] Address and indirection operators * ```&```: called address of * ```*```: called value of or indirection * The unary & operator yields the address of its operand. If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’. If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue. > 若```&```的 operand 是```*```兩個 operator都會被省略 * Similarly, if the operand is the result of a [] operator, neither the & operator nor the unary * that is implied by the [] is evaluated and the result is as if the & operator were removed and the [] operator were changed to a + operator. Otherwise, the result is a pointer to the object or function designated by its operand. > 同樣,若 operand 是 result of a `[]` ,則 `[] 中隱含的 *` 及 &` 都會被忽略 ```c char str[] = "Hello world"; printf("%x %x\n", str, &str); ``` 會得到輸出 ``` 75b13f7c 75b13f7c ``` * `char *a` 與 `a[]` 邏輯上相等但 `sizeof(a)` 會是一個 word的大小, 而 `sizeof(a[])` 會等於陣列長度,所以兩種表達方式不相等 * The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined. > e.g. `int *a` operand `a` has type pointer to int > lvalue means locator value, 代表可存取的資源 * 而根據 C99 [6.5.3.3] Unary arithmetic operators * The operand of the unary + or - operator shall have arithmetic type; of the ~ operator, integer type; of the ! operator, scalar type. > 在對 Address and indirection operators 的結果作運算時要注意型態,且沒有乘除法 ### C99 [6.2.5] Types *incomplete types (types that describe objects but lack information needed to determine their sizes). > forward declaration 的變數是 incomplete type * ++, --, +=, -= 等操作,都是對 scalar * scalar: 只有大小,可用 sizeof 來得知單位大小, 對 scalar 做 ++ 相當於遞增一單位 * Arithmetic types and pointer types are collectively called scalar types. Array and structure types are collectively called aggregate types * An array type of unknown size is an incomplete type. It is completed, for an identifier of that type, by specifying the size in a later declaration (with internal or external linkage). A structure or union type of unknown content (as described in 6.7.2.3) is an incomplete type. It is completed, for all declarations of that type, by declaring the same structure or union tag with its defining content later in the same scope. > 若 type 不是 incomplete type 或 大小會變動的陣列,則會有固定的記憶體空間。 > forward declaration ``` struct b; // no definition -> forward declaration ``` :::warning b = ++a 相當於 b = a, b = b + 1 所以做幾次 ++a a 的值都不變 a++ ++ -- 的結果是 rvalue 不能對其再做運算 ::: * static: 只有在第一次呼叫會做初始化 ```c void foo () { static int a = 3; ++a; printf("%d\n", a); } int main () { foo(); foo(); foo(); } ``` ``` 4 5 6 ``` * A pointer type may be derived from a function type, an object type, or an incomplete type, called the referenced type.Apointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a referenced type is called ‘‘pointer type derivation’’. * Array, function, and pointer types are collectively called derived declarator types. A declarator type derivation from a type T is the construction of a derived declarator type from T by the application of an array-type, a function-type, or a pointer-type derivation to T. > derived declarator types: 透過宣告衍生的型態 > e.g. int *: pointer to int * The type designated as ‘‘float *’’ has type ‘‘pointer to float’’. Its type category is pointer, not a floating type. The const-qualified version of this type is designated as ‘‘float * const’’ whereas the type designated as ‘‘const float *’’ is not a qualified type — its type is ‘‘pointer to const qualified float’’ and is a pointer to a qualified type. ``` int const *p_ci; // Pointer to constant int int const (*p_ci); // Pointer to constant int int *const cp_i; // Constant pointer to int int (*const cp_i); // Constant pointer to int ```` * 用 pointer to pointer 擴展變數的 lifetime * void *, incomplete type, pointer to pointer - [函式呼叫篇](https://hackmd.io/@sysprog/c-function) ### void * ### gdb 編譯時加上 -g 以利後續 GDB 追蹤: `gcc -o stack -g stack.c` `$ gdb -q a` ``` b (行數 or 函式名稱): 設 break point r: 執行 n: 可直接一次執行整個 function s: 遇到 function 進入一行一行執行 finish: 把 loop 一次執行完 p a: print variable a ``` ### lvalue The name ‘‘lvalue’’ comes originally from the assignment expression E1 = E2, in which the left operand E1 is required to be a (modifiable) lvalue. It is perhaps better considered as representing an object ‘‘locator value’’. >lvalue 是個物件的表示式 (an expression referring to an object),該物件的型態可以是一般的 object type 或 incomplete type,但不可為 void。換句話說,運算式的結果會是個有名稱的物件。 What is sometimes called ‘‘rvalue’’ is in this International Standard described as the ‘‘value of an expression’’. `++(a++); // error` 因為 a++ 會回傳 a 的 value,而這個 value 是暫存值也就是個 non-lvalue,而 ++() 這個 operator 的 operand 必須要是一個 lvalue,因為要寫回 data,需要有地方 (location) 可寫入 ## graphviz dot C:\Users\terry\Desktop\test.dot -Tpng -o image.png ``` digraph pic1 { rankdir = LR; {rank=1 head->2->4->5->8->9}; } ```