Wednesday, December 29, 2021

C 指標介紹

简化一些 C++ 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的

& 不要都念成 and,涉及指標操作的時候,要讀為 “address of”

在 開發工具和規格標準 篇提過參考第一手資料的重要性,以下 ISO/IEC 9899 (簡稱 “C99”)和指標相關的描述:

  • 規格書 (PDF) 搜尋 “object”,共出現 735 處

    • 搜尋 “pointer”,共出現 637 處。有趣的是,許多教材往往不談 object,而是急著談論 pointer,殊不知,這兩者其實就是一體兩面
    • object != object-oriented
      • 前者的重點在於「資料表達法」,後者的重點在於 “everything is object”
    • C11 (ISO/IEC 9899:201x) / 網頁版
  • & 不要都念成 and,涉及指標操作的時候,要讀為 “address of”

    • C99 標準 [6.5.3.2] Address and indirection operators 提到 ‘&’ address-of operator
  • C99 [3.14] object

    • region of data storage in the execution environment, the contents of which can represent values
    • 在 C 語言的物件就指在執行時期,資料儲存的區域,可以明確表示數值的內容
    • 很多人誤認在 C 語言程式中,(int) 7 和 (float) 7.0 是等價的,其實以資料表示的角度來看,這兩者截然不同,前者對應到二進位的 “111”,而後者以 IEEE 754 表示則大異於 “111”
  • C99 [6.2.5] Types

    • A pointer type may be derived from a function type, an object type, or an incomplete type, called the referenced type. A pointer 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’’.

    注意到術語!這是 C 語言只有 call-by-value 的實證,函式的傳遞都涉及到數值
    這裡的 “incomplete type” 要注意看,稍後會解釋。要區分 char [] 和 char *

    • Arithmetic types and pointer types are collectively called scalar types. Array and structure types are collectively called aggregate types.

    注意 “scalar type” 這個術語,日後我們看到 ++--+=-= 等操作,都是對 scalar (純量)

    [來源] 純量只有大小,它們可用數目及單位來表示(例如溫度 = 30oC)。純量遵守算數和普通的代數法則。注意:純量有「單位」(可用 sizeof 操作子得知單位的「大小」),假設 ptr 是個 pointer type,對 ptr++ 來說,並不是單純 ptr = ptr + 1,而是遞增或遞移 1 個「單位」

    • 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 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.

    這是 C/C++ 常見的 forward declaration 技巧的原理,比方說我們可以在標頭檔宣告 struct GraphicsObject; (不用給細部定義) 然後 struct GraphicsObject *initGraphics(int width, int height); 是合法的,但 struct GraphicsObject obj; 不合法

    • 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,讀到此處會感到驚訝者,表示不夠理解 C 語言


int main() {
    typedef void (*funcptr)();
    (* (funcptr) (void *) 0)();
}

main:
        push    rax
        xor     eax, eax
        call    rax
        xor     eax, eax
        pop     rdx
        ret

Segmentation fault (core dumped)

我去呼叫地址為 0 的函數

0這個地址不是使用者層級可以呼叫

Reference:
https://hackmd.io/@sysprog/c-pointer
1:18:08

No comments:

Post a Comment

n8n index

 【n8n免費本地端部署】Windows版|程式安裝x指令大補帖  【一鍵安裝 n8n】圖文教學,獲得無限額度自動化工具&限時免費升級企業版功能