3.25.2007

IRC Interview with WanCW about Function Pointer in C

以下的內容是從舊的 blog 轉過來的,當初的發文時間在 2006,05,18。其內容是關於 C 的 Function Pointer 與所謂的 callback 應用。

15:25 <Adios> == BEGIN ==
15:25 -%- Irssi: Pasting 9 lines to WanCW. Press Ctrl-K if you wish to do this or Ctrl-C to cancel.
15:25 <Adios> { /* Welcome to array of function pointers */
15:25 <Adios> int i;
15:25 <Adios> void (*array[])(int *) = {increase_int, increase_int, square_int, NULL};
15:25 <Adios> for(i=0; array[i]!= NULL; i++) {
15:25 <Adios> (*(array+i))(a);
15:25 <Adios> printf("After %p, c = %d\n", array[i], c);
15:25 <Adios> }
15:25 <Adios> }
15:25 <Adios> return 0;==
15:25 <Adios> == end
15:26 <Adios> 我剛剛把 jypan 之前較的拿出來看
15:26 <Adios> C 可以這樣寫喔@@? void(*arra[])(int *) = () 這行
16:17 <WanCW> why not? array of function pointer
16:17 <Adios> 那一段看不懂!
16:17 <WanCW> void (T)(int *)
16:17 <WanCW> 這樣懂嗎?
16:18 <Adios> 是這裡不懂吧
16:18 <WanCW> void (*T)(int *)
16:18 <WanCW> 這樣才對
16:18 <WanCW> 哪裡?
16:18 <Adios> 就是這裡
16:18 <WanCW> void func(int *)
16:18 <WanCW> 一個叫做 func 的 function
16:18 <WanCW> void (*pFunc)(int *)
16:19 <WanCW> 一個叫做 pFunc 的 function pointer, 指向跟 func 長的一樣的 function
16:19 <WanCW> void (*apFunc[])(int *)
16:20 <WanCW> apFunc 是一個 array, 裡面放的都是像 pFunc 的東西
16:20 <WanCW> 了解?
16:20 <Adios> 還沒 我思考一下
16:21 <WanCW> pFunc = &func
16:21 <WanCW> apFunc[0] = pFunc
16:21 <WanCW> 大概是這種用法
16:21 <WanCW> func(&i);
16:21 <WanCW> (*pFunc)(&i)
16:22 <WanCW> 阿..不對, 是:
16:22 <WanCW> pFunc(&i)
16:22 <WanCW> 其實 "func" 也是一個指標
16:22 <WanCW> 所以應該是
16:22 <WanCW> pFunc = func # 很怪吧? XD
16:25 <Adios> 還有那個 { } 的意思在C裡面是怎樣?
16:25 <WanCW> init an aray
16:25 <WanCW> int a[] = {1, 2, 3};
16:25 <WanCW> a[0] == 1, and so on.
16:25 <Adios> oh 我說那個 一開始的 { 跟最後依航的 }
16:25 <Adios> 就是block
16:26 <WanCW> just a block
16:26 <Adios> 我以為C應定要有 int main () { }
16:26 <WanCW> to create a new scope
16:26 <WanCW> 剛剛那是片斷吧?
16:26 <Adios> 不是耶
16:26 <WanCW> 最後面還有 return 0; 呀
16:26 <Adios> http://ant.comm.ccu.edu.tw/course/92_Programming/2_SampleCode/040319_pointer.c
16:27 <Adios> 喔 我是說 我以為那是依個函式
16:28 <WanCW> 所以他是一個 block to create a scopr
16:28 <WanCW> 因為在 C 裡面這樣不合法:
16:28 <WanCW> func ()
16:28 <WanCW> {
16:28 <WanCW> int a;
16:28 <WanCW> a++;
16:28 <WanCW> int b; // ERROR!!!
16:28 <WanCW> }
16:28 <Adios> oh
16:29 <Adios> 所以直接依個 不具名的 block
16:29 <Adios> 就create依個scope了
16:29 <WanCW> yes, 變成這樣既就可以:
16:29 <WanCW> func ()
16:29 <WanCW> {
16:29 <WanCW> int a;
16:29 <WanCW> a++;
16:29 <WanCW> { int b; }
16:29 <WanCW> }
16:29 <Adios> 我從來不知道 Orz
16:29 <Adios> 我以為C沒有
16:29 <Adios> 原來C什麼都有
16:30 <WanCW> 你錯怪 C 了
16:31 <Adios> increase_int 與 & increase_int 都是回傳他的起始位置吧?
16:31 <Adios> &increate_int vs increate_int
16:31 <WanCW> yes, this is tricky
16:32 <WanCW> 就像 int A[] = { 1, 2}
16:32 <WanCW> &A == A
16:32 <Adios> ok
16:32 <WanCW> try it by yourself. :p
16:38 <Adios> 好我懂了
16:38 <Adios> exp++
16:39 <WanCW> level up?
16:39 <Adios> not yet
16:39 <Adios> 這樣的原理 有沒有通常會運用在怎樣的 手法上?
16:40 <WanCW> 哪個 function pointer?
16:40 <Adios> function pointer
16:40 <WanCW> call back
16:41 <WanCW> 最出名的應用
:41 <WanCW> qsort
16:41 <Adios> 會什麼要叫做 callback 我查過google還是不鳥
16:41 <WanCW> I call you and give you a callback, you call back to me by callback.
16:42 <Adios> 簡單明瞭 這樣說就瞭了
16:43 <Adios> 所以它可以讓 其他function 直接跳到 另依個fuction 而不用透過一層層的return這樣?
16:43 <WanCW> 本來是我 call 你, 但是我要讓你能再 回call 我, 就給你一個 "callback"
16:43 <WanCW> 不太懂你的意思
16:44 <Adios> 如果main 必須要執行兩個functino A, B , 這樣的話 要讓A作完以後 return,B作完以後再reutrn
16:45 <Adios> 用callback 的話 A做完可以直接B媽
16:45 <WanCW> no, no, no.
16:46 <WanCW> 實例 qsort:
16:46 <WanCW> qsort 裡面, 會用到 a < b,
16:47 <WanCW> 但是 C 沒有 function overriding, 你要比較特別的資料型態(像字串) 必須:
16:47 <WanCW> comp (a, b)
16:47 <WanCW> 那不同的型態有不同的 compare func,
16:48 <Adios> Y
16:48 <WanCW> 所以我們會 qsort(A, B, CompFunc)
16:48 <WanCW> 讓 qsort 在需要的時候, 去呼叫 CompFunc
16:48 <WanCW> 另外一個用途就是像 jypan 寫的, 簡陋的多型
16:49 <WanCW> pFunc (a, b); <- different func do diff thing.
16:49 <WanCW> 我決定大的邏輯(流程?), 你提供 callback 提供細部實做
16:49 <WanCW> --
16:50 <WanCW> 例如說: 資料儲存後端可以變化
16:50 <WanCW> 那我就可以用 functoin pointer 來切換
16:50 <WanCW> 但是程式邏輯不需要改.
16:50 <WanCW> --
16:50 <Adios> 所以這也是C 要做成多型的手法!
16:51 <WanCW> 是的
16:51 <WanCW> 其實, C++ 的多型就是用 function pointer table 來實做的
16:51 <Adios> !!
16:51 <WanCW> class A -> f1, f2, f3
16:51 <WanCW> calss B 繼承 A, 改寫 f2
16:52 <WanCW> 那他的 function pointer table 的 f2 就跟 A 的不一樣,
16:52 <WanCW> 其他一樣
16:52 <WanCW> b.f2 (...) ==> b.funcTable[INDEX_OF_f2] (...)
16:53 <WanCW> b.f2 (...) ==> funcTableOfB [INDEX_OF_f2] (b, ...)
16:53 <WanCW> 後面才對
16:53 <WanCW> b 就變成 this!
16:53 <WanCW> 詳情請看 Inside C++ Object Model XD
16:53 <Adios> 這太深奧了~! 就向史密斯電子一樣
16:54 <WanCW> 嗯, Implementation of C++ is very tricky.
16:54 <WanCW> ugly
16:54 <Adios> 我再慢慢消化吧
16:54 <Adios> 我問簡單的
16:54 <WanCW> 會用就好, 等你有需要時, 自然就會想到了. XD
16:54 <WanCW> 嗯.?
16:54 <Adios> 本來是我 call 你, 但是我要讓你能再 回call 我, 就給你一個 "callback"
16:55 <Adios> A call B, A give B callback, B can callback to A
16:55 <WanCW> yeap
16:55 <Adios> 那未什麼不讓 B return 就好
16:55 <WanCW> 錯了
16:55 <WanCW> A call B, A give B callback C, B can callback to A'side
16:56 <WanCW> 兩個是不同 function
16:56 <Adios> 哪兩個是不同的funciton!
16:56 <WanCW> ruby 的 blocks 其實就是 callback. 只是與法比較高階
16:56 <WanCW> 語法
16:56 <WanCW> anArray.each {|x| puts x }
16:57 <WanCW> --
16:57 <Adios> 越來越混亂壓~
16:57 <WanCW> for_each (anAray, F)
16:57 <WanCW> --
16:57 <WanCW> restart.
16:57 <WanCW> anArray.each {|x| puts x }
16:57 <WanCW> 上面那行你懂意思吧?
16:57 <Adios> puts each x in array
16:58 <WanCW> yes, and I show you a C++ segment do the same thing.
16:58 <Adios> go:
17:00 <WanCW> void f (int x)
17:00 <WanCW> {
17:00 <WanCW> printf ("%d\n", x);
17:00 <WanCW> }
17:00 <WanCW> for_each (int A[], int size, void (*pf)(int))
17:00 <WanCW> {
17:00 <WanCW> int i;
17:00 <WanCW> for (i=0; i<size; ++i)
17:00 <WanCW> pf(x);
17:00 <WanCW> }
17:00 <WanCW> _END_
17:00 <WanCW> then:
17:00 <WanCW> int anArray[] = {1, 2, 3};
17:01 <WanCW> for_each (anArray, 3, f);
17:02 <WanCW> =====
17:02 <WanCW> Array.each in Ruby may be this way:
17:03 <WanCW> def each(ary)
17:03 <WanCW> == abort
17:03 <WanCW> 看這個網頁
17:03 <WanCW> http://www.ruby-doc.org/core/classes/Array.src/M000412.html
17:03 <WanCW> rb_yield 那行就是呼叫 callback # 'yield' means call the block in Ruby language.
17:04 <WanCW>
17:04 <WanCW> 不過,你為啥現在回去看 C ?
17:05 <Adios> 想到callback 沒有懂所以要把它弄懂
17:05 <WanCW> oh~
17:05 <Adios> 以剛剛的C++ code蘭說的話 他可以直接把
17:06 <Adios> for( i =0; i<size; ++i) pf(x);
17:06 <Adios> 把pf(x) 直接call f 不就好了嗎
17:07 <WanCW> 那是因為現在兩個部份是一起寫的,
17:07 <WanCW> 如果你想寫個 linked-list library 提供 each 的功能呢?
17:07 <WanCW> 那 pf 就是不確定的啦
17:08 <WanCW> 等著 library user 決定
17:08 <WanCW> 這時候就要用 call back.
17:08 <WanCW> --
17:08 <Adios> 所以就像是一個 interface
17:08 <WanCW> 我會說是插座
17:08 <WanCW> yeap, but say the same thing.
17:08 <Adios> 好插座
17:10 <WanCW> 嗯
17:10 <Adios> 好我大概瞭了 #callback是什麼 為什麼要用callback~
17:10 <WanCW> 恭喜
17:10 <WanCW> Adios 習得 callback 技能.
17:10 <Adios> 我po 在 tdiary?
17:10 <WanCW> anywhere u like. :)
17:10 <Adios> title: IRC Interview with WanCW
17:11 <WanCW> # 你不想 po 板上, 怕被發現你不會 call back XD
17:11 <WanCW> kidding
17:11 <WanCW> 吃飯去, c u
17:11 <Adios> 板上太難看 XD
17:11 <WanCW> 哈哈~ XD
17:11 <Adios> 我用courier打B阿會太長