作者ericsk (认真的艾瑞克)
看板b94902xxx
标题[秘技] 使徒七同步秘技 (2)
时间Thu Nov 3 12:13:23 2005
[function pointer是什麽鬼?]
大家都知道指标(pointer)是用来存记忆体位址的,在 C 语言中,
你定义的 function 也会在记忆体中占有一席之地。这时你就会开始思考
了,如果要指到一个 int 变数的位址,我们会用 int * 的指标,如果
是要指到 char 变数的位址,我们就会用 char *,那指到函式要用什麽呢?
这里先提一点, function 跟 array 有一个相同的性质,那就是它的名称
就表示它在记忆体中的位址,也就是说
void foo(int a, int b)
{
...
}
这个函式, foo 就是指到这个 function 的位址,那 foo 的资料型态是什麽?
照定义,那就是 void (*)(int, int) ,这包括了 function 回传值
资料型态,以及它参数的型态。
所以我们可以写出这样的 code:
(接上面的 code)
void (*c)(int, int); /* 宣告一个指标变数 c */
c = foo; /* 把 foo 的位址 assign 给 c */
.....
c(a, b);
在这个例子中,我们把 foo 的位址 assign 给 c,所以我们用 c 来呼叫
function 的动作完全等同於用 foo 来呼叫 function 一样。
[qsort大蒐秘]
qsort 是标准 C 函式库中用来 排序一个阵列 的函式。函式的介面
是这样的:
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));
这个函式参数总共有 4 个,分别是 base, nmemb, size, 以及 compar。
base 是 欲排序阵列开始的位址。
nmemb 是 阵列总共有多少个元素。
size 是 每个元素的大小。
compar 是一个 function pointer,qsort 透过这个 function pointer
来呼叫 比较两元素大小 的函式,用来作为排序过程中的比对动作。
比方说,如果我们要排序(由小到大)一个阵列 int a[10]; 的时候,
可以写成:
int c_int(const void *x, const void *y)
{
int ret = *(int *)x - *(int *)y;
return ret;
}
....
int a[10];
....
qsort(a, 10, sizeof(int), c_int);
透过上面这段程式码,a 阵列就会由小到大排序好了。而这一整个动作
的关键就在 c_int 这个 compare function。
试着想像,我们说一个阵列由小到大排序好,这意味着元素间有一个
「大, 小」的关系,任两个元素一定可以比较出来谁大谁小或是相等。
(用离散的讲法,这个阵列的元素有 total ordering relation)
然而, qsort 为了保持弹性,它让「比较」这件事交给你来处理,因为
有的时候我们要排序的阵列,阵列里的元素不一定是 一个整数 资料,有
可能是其它的物件,或是你自订了一个比较大小的规则,所以 qsort
保留了这个空间让你自己实作,这便是它需要一个 compar 参数的原因。
在上面的例子中,我们实作了一个 function c_int ,然後传到 qsort 里面,
让 qsort 透过 compar 使用 c_int 这个 function 来作比较的动作。
因为我们要比较的东西是 两个 int 的资料,所以 c_int 的两个参数在
进入 function 後就要转型成 int * 後再取值,这样才能正确地比较
「两个 int」。
那,我 return 两个参数的差,这是什麽意义呢?
在排序的过程中,当两个元素作完比较之後,就要决定谁在前谁在後,
而在 qsort 的规则里,如果透过 compar 比较後,传回一个 负数值,
那麽就会把第一个参数摆在前面;传回一个 正数值 时,就会把第二个
参数摆在前面;传回 0 的话表示相等。所以我回传 x - y 的值,
若为负,则 x 比 y 小,所以 x 会放在 y 前,以此类推,排序结束後,
阵列就会是由小到大排序完成了。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.112.30.82
1F:推 purincess: 好人助教我们敬佩您! 11/03 13:44
2F:推 anauma: 好人助教我们敬佩您! 11/03 14:20
3F:→ kcir: 好人助教我们敬佩您! 11/03 16:25
4F:推 doudi: 好人助教我们敬佩您! 11/03 17:06
5F:推 tsucci: 好人助教我们敬佩您! 11/03 19:39
6F:推 hamigwa: 好人助教我们敬佩您! 11/03 22:16
7F:推 david4751125: 好人助教我们敬佩您! 11/03 22:39
8F:推 victo: 好人助教我们敬佩您! 11/03 22:59
9F:推 dongogo: 好人助教我们敬佩您! 11/03 23:10
10F:推 NeantD: 好人助教我们敬佩您! 11/04 00:32
11F:推 collala: 好人助教我们敬佩您! 11/04 20:37