Hackpads are smart collaborative documents. .

Jie-Han Chen

794 days ago
Unfiled. Edited by Jie-Han Chen 794 days ago
Jie-Han C Day2 第三題
 
這是我自己的寫法,目前看來還有一些可以改進的地方
像是 branch 的辦別在字串很大的時候,需要多次判斷,這會拖慢效率。
 
 
原始想法:
首尾互換,到中間的時候就停止。
 
改進:
可以把 swap function 嵌入在 reverse 裡面減少 function call 的 overhead
使用 static 變數仍然有同時存取修改的問題。
 
 
 
381 days ago
Unfiled. Edited by Jie-Han Chen 381 days ago
Jim H 你所不知道的C語言:指標篇
「指標」扮演「記憶體」和「物件」之間的橋樑  [編輯本頁]; [系列講座]
Copyright (慣C) 2015 宅色夫
 
 
  • 這個講座並非「頭腦體操」
 
  • (*(void(*)())0)();
其實可改寫為:
  • typedef void (*funcptr)();
  • (* (funcptr) 0)();
 
godbolt : 直接在網頁上看到 gcc 生成的程式碼
[ Code editor ]
  • int main() {
  •     typedef void (*funcptr)();
  •     (* (funcptr) (void*) 0)();
  • }
[ Assembly output ] `-Os` (空間最佳化)
  • main:
  •         pushq        %rax
  •         xorl        %eax, %eax
  •         call        *%rax
  •         xorl        %eax, %eax
  •         popq        %rdx
  •         ret
 
  • ISO/IEC 9899 (簡稱 "C99")
  • 規格書 (PDF) 搜尋 "object",共出現 735 處
  • 搜尋 "pointer",共出現 637 處。有趣的是,許多教材往往不談 object,而是急著談論 pointer,殊不知,這兩者其實就是一體兩面
  • object != object-oriented
  • 前者的重點在於「資料表達法」,後者的重點在於 "everything is object"
  • 從第一手資料學習:大文豪寫作都不免要查字典,庸俗的軟體開發者如我們,難道不需要翻閱語言規格書嗎?難道不需要搞懂術語定義和規範嗎?
  • [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"
  • [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.
  • ==> 注意生命週期 (lifetime) 的概念,中文講「初始化」時,感覺像是「盤古開天」,很容易令人誤解。其實 initialize 的英文意義很狹隘: "to set (variables, counters, switches, etc.) to their starting values at the beginning of a program or subprogram."
  • The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address and retains its last-stored value throughout its lifetime. If an object is referred to outside of its lifetime, the behavior is undefined.
  • ==> 在 object 的生命週期以內,其存在就意味著有對應的常數記憶體位址。注意,C 語言永遠只有 call-by-value
  • The value of a pointer becomes indeterminate when the object it points to reaches the end of its lifetime.
  • ==> 作為 object 操作的「代名詞」(alias) 的 pointer,倘若要在 object 生命週期以外的時機,去取出 pointer 所指向的 object 內含值,是未知的。考慮以下操作 `ptr = malloc(size); free(ptr);` 倘若之後做 `*ptr`,這個 allocated storage 已經超出原本的生命週期
  • An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration.
  • [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 語言
  • ==> "derivative" 這詞在是微積分學中就是導數。一個函數在某一點的導數描述了這個函數在這一點附近的變化率。導數的本質是通過極限的概念對函數進行局部的線性逼近。
  • (一個實值函數的圖像曲線。函數在一點的導數等於它的圖像上這一點處之切線的斜率)
  • 回到 C 語言,你看到一個數值,是 scalar,但可能也是自某個型態衍生出的 declarator type derivation,實際對應到 array, function, pointer 等型態的 derivation
  • (練習題) 設定絕對地址為 `0x67a9` 的 32-bit 整數變數的值為 `0xaa6`,該如何寫?
  • *(int32_t * const) (0x67a9) = 0xaa6;
  • /* Lvalue */
  • A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.
  • ==> 關鍵描述!規範 `void *``char *` 彼此可互換的表示法
  • void *memcpy(void *dest, const void *src, size_t n);
 
  • C99 規格書的解說就比很多書本清楚,何必捨近求遠呢?
  • EXAMPLE 1 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.
  • EXAMPLE 2 The type designated as "`struct tag (*[5])(float)` has type "array of pointer to function returning struct tag'". The array has length five and the function has a single parameter of type float. Its type category is array.
 
 
  • 英文很重要
安裝 cdecl 程式,可以幫你產生 C 程式的宣告。
  • sudo apt-get install cdecl
使用案例
  • $ cdecl
  • cdecl> declare a as array of pointer to function returning pointer to function returning pointer to char
會得到以下輸出:
  • char *(*(*a[])())()
 
把前述 C99 規格書的描述帶入,可得:
  • cdecl> declare array of pointer to function returning struct tag
  • struct tag (*var[])()
 
如果你沒辦法用英文來解說 C 程式的宣告,通常表示你不理解!
cdecl 可以解釋 C 程式宣告的意義,比方說:
  • cdecl> explain char *(*fptab[])(int)
  • declare fptab as array of pointer to function (int) returning pointer to char
 
 
  • `void *` 之謎
  • `void` 在最早的 C 語言是不存在的,直到 C89 才確立,為何要設計這樣的型態呢?
  • 最早的 C 語言中,任何函式若沒有特別標注返回型態,一律變成 `int` (伴隨著 `0` 作為返回值),但這導致無從驗證 function prototype 和實際使用的狀況
...
738 days ago
Unfiled. Edited by Jie-Han Chen 738 days ago
Jul 19, 2015 問答
 
381 days ago
Unfiled. Edited by Jie-Han Chen 381 days ago
Jim H 你所不知道的C語言:指標篇
「指標」扮演「記憶體」和「物件」之間的橋樑  [編輯本頁]; [系列講座]
Copyright (慣C) 2015 宅色夫
 
 
  • 這個講座並非「頭腦體操」
 
  • (*(void(*)())0)();
其實可改寫為:
  • typedef void (*funcptr)();
  • (* (funcptr) 0)();
 
godbolt : 直接在網頁上看到 gcc 生成的程式碼
[ Code editor ]
  • int main() {
  •     typedef void (*funcptr)();
  •     (* (funcptr) (void*) 0)();
  • }
[ Assembly output ] `-Os` (空間最佳化)
  • main:
  •         pushq        %rax
  •         xorl        %eax, %eax
  •         call        *%rax
  •         xorl        %eax, %eax
  •         popq        %rdx
  •         ret
 
  • ISO/IEC 9899 (簡稱 "C99")
  • 規格書 (PDF) 搜尋 "object",共出現 735 處
  • 搜尋 "pointer",共出現 637 處。有趣的是,許多教材往往不談 object,而是急著談論 pointer,殊不知,這兩者其實就是一體兩面
  • object != object-oriented
  • 前者的重點在於「資料表達法」,後者的重點在於 "everything is object"
  • 從第一手資料學習:大文豪寫作都不免要查字典,庸俗的軟體開發者如我們,難道不需要翻閱語言規格書嗎?難道不需要搞懂術語定義和規範嗎?
  • [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"
  • [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.
  • ==> 注意生命週期 (lifetime) 的概念,中文講「初始化」時,感覺像是「盤古開天」,很容易令人誤解。其實 initialize 的英文意義很狹隘: "to set (variables, counters, switches, etc.) to their starting values at the beginning of a program or subprogram."
  • The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address and retains its last-stored value throughout its lifetime. If an object is referred to outside of its lifetime, the behavior is undefined.
  • ==> 在 object 的生命週期以內,其存在就意味著有對應的常數記憶體位址。注意,C 語言永遠只有 call-by-value
  • The value of a pointer becomes indeterminate when the object it points to reaches the end of its lifetime.
  • ==> 作為 object 操作的「代名詞」(alias) 的 pointer,倘若要在 object 生命週期以外的時機,去取出 pointer 所指向的 object 內含值,是未知的。考慮以下操作 `ptr = malloc(size); free(ptr);` 倘若之後做 `*ptr`,這個 allocated storage 已經超出原本的生命週期
  • An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration.
  • [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 語言
  • ==> "derivative" 這詞在是微積分學中就是導數。一個函數在某一點的導數描述了這個函數在這一點附近的變化率。導數的本質是通過極限的概念對函數進行局部的線性逼近。
  • (一個實值函數的圖像曲線。函數在一點的導數等於它的圖像上這一點處之切線的斜率)
  • 回到 C 語言,你看到一個數值,是 scalar,但可能也是自某個型態衍生出的 declarator type derivation,實際對應到 array, function, pointer 等型態的 derivation
  • (練習題) 設定絕對地址為 `0x67a9` 的 32-bit 整數變數的值為 `0xaa6`,該如何寫?
  • *(int32_t * const) (0x67a9) = 0xaa6;
  • /* Lvalue */
  • A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.
  • ==> 關鍵描述!規範 `void *``char *` 彼此可互換的表示法
  • void *memcpy(void *dest, const void *src, size_t n);
 
  • C99 規格書的解說就比很多書本清楚,何必捨近求遠呢?
  • EXAMPLE 1 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.
  • EXAMPLE 2 The type designated as "`struct tag (*[5])(float)` has type "array of pointer to function returning struct tag'". The array has length five and the function has a single parameter of type float. Its type category is array.
 
 
  • 英文很重要
安裝 cdecl 程式,可以幫你產生 C 程式的宣告。
  • sudo apt-get install cdecl
使用案例
  • $ cdecl
  • cdecl> declare a as array of pointer to function returning pointer to function returning pointer to char
會得到以下輸出:
  • char *(*(*a[])())()
 
把前述 C99 規格書的描述帶入,可得:
  • cdecl> declare array of pointer to function returning struct tag
  • struct tag (*var[])()
 
如果你沒辦法用英文來解說 C 程式的宣告,通常表示你不理解!
cdecl 可以解釋 C 程式宣告的意義,比方說:
  • cdecl> explain char *(*fptab[])(int)
  • declare fptab as array of pointer to function (int) returning pointer to char
 
 
  • `void *` 之謎
  • `void` 在最早的 C 語言是不存在的,直到 C89 才確立,為何要設計這樣的型態呢?
  • 最早的 C 語言中,任何函式若沒有特別標注返回型態,一律變成 `int` (伴隨著 `0` 作為返回值),但這導致無從驗證 function prototype 和實際使用的狀況
...
738 days ago
Unfiled. Edited by Jie-Han Chen 738 days ago
Aug 3, 2015 問答
 
  • 1. debug mode 是什麼?
  • 2. 最下面的對話框內容,有同學表示沒有找到對應的解釋
 
738 days ago
Unfiled. Edited by Jie-Han Chen 738 days ago
Jul 18, 2015 問答
 

Contact Support



Please check out our How-to Guide and FAQ first to see if your question is already answered! :)

If you have a feature request, please add it to this pad. Thanks!


Log in