在將qsort函數(shù)應(yīng)用于對(duì)指針數(shù)組與二維數(shù)組排序時(shí),傳遞給compare函數(shù)的參數(shù)類型是不同的首先,我們舉個(gè)簡(jiǎn)單的例子,先將qsort對(duì)整數(shù)數(shù)組排序:
1 int
2 cmp(const void *arg1, const void *arg2)
3 {
4 return (*(int *)arg1)-(*(int *)arg2);
5 }
6
7 int
8 main(int argc, char **argv)
9 {
10 int i;
11 int arr[] = {3, 1, 5, 2, 4};
12 qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(int), cmp);
13 }
排序針對(duì)的是數(shù)組里的元素而言的,這里整數(shù)數(shù)組的元素就是整數(shù),因此qsort的第三個(gè)參數(shù)就是sizeof(int),而傳遞給比較函數(shù)cmp的參數(shù)就是相對(duì)應(yīng)的指向整數(shù)的指針
接著,我們來(lái)看看指針數(shù)組的情形:
1 int
2 cmp(const void *arg1, const void *arg2)
3 {
4 return strcmp((*(char **)arg1), (*(char **)arg2));
5 }
6
7 int
8 main(int argc, char **argv)
9 {
10 int i;
11 /* pointer array */
12 char *str[] = {"java", "c", "python", "perl"};
13 qsort(str, sizeof(str)/sizeof(str[0]), sizeof(char *), cmp);
14 }
這里的理解其實(shí)跟整數(shù)數(shù)組差不多,關(guān)鍵是抓住數(shù)組里元素的類型,既然稱之為指針數(shù)組,那數(shù)組元素的類型自然就是指針,因此qsort的第三個(gè)參數(shù)就是sizeof(char *),而傳遞給比較函數(shù)cmp的參數(shù)就是相對(duì)應(yīng)的指向指針的指針,這里即char **類型
二維數(shù)組的理解最為復(fù)雜,代碼如下:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4
5 int
6 cmp1(const void *arg1, const void *arg2)
7 {
8 return strcmp((*((char (*)[])arg1)), (*((char (*)[])arg2)));
9 }
10
11 int
12 cmp2(const void *arg1, const void *arg2)
13 {
14 return strcmp((char *)arg1, (char *)arg2);
15 }
16
17 int
18 main(int argc, char **argv)
19 {
20 int i;
21 char str1[4][8] = {"java", "c", "python", "peal"};
22 printf("COMPARE-FUNCTION-1\n");
23 qsort(str1, 4, sizeof(str1[0]), cmp1);
26
27 char str2[4][8] = {"java", "c", "python", "peal"};
28 printf("COMPARE-FUNCTION-2\n");
29 qsort(str2, 4, sizeof(str2[0]), cmp2);
34 }
這里cmp1與cmp2都能正常的工作(*^__^*) 嘻嘻……
還是按照上述方法來(lái)分析,抓住數(shù)組元素的類型來(lái)入手,二維數(shù)組實(shí)際上就是數(shù)組的數(shù)組,因此二維數(shù)組的元素類型就是一維數(shù)組,因此qsort的第三個(gè)參數(shù)就是sizeof(str1[0])或sizeof(str2[0]),那傳遞給比較函數(shù)的參數(shù)應(yīng)該就是指向數(shù)組的指針,這點(diǎn)可以通過(guò)gdb設(shè)置斷點(diǎn)來(lái)得到證實(shí):
1 (gdb) p &str1[0]
2 $1 = (char (*)[8]) 0xbffff2cc
3 (gdb) p &str1[1]
4 $2 = (char (*)[8]) 0xbffff2d4
5
6 Breakpoint 2, cmp1 (arg1=0xbffff2cc, arg2=0xbffff2d4) at char_test2.c:8
7 8 return strcmp((*((char (*)[])arg1)), (*((char (*)[])arg2)));
8 (gdb) p arg1
9 $3 = (const void *) 0xbffff2cc
10 (gdb) p arg2
11 $4 = (const void *) 0xbffff2d4
12 (gdb) p *(char (*)[])arg1
13 $5 = "j"
14 (gdb) p *(char (*)[8])arg1
15 $6 = "java\000\000\000"
通過(guò)第2行與第9行的比較可以發(fā)現(xiàn),比較函數(shù)的參數(shù)arg1其實(shí)就是&str1[0],類型為char (*)[],這也是為什么cmp1能正常工作的原因
那么cmp2呢,它為什么正確呢?
在cmp1中:
strcmp((*((char (*)[])arg1)), (*((char (*)[])arg2))); 這里傳遞給strcmp的參數(shù)之所以不會(huì)出錯(cuò),是因?yàn)槲覀儗rg1解地址操作獲得一個(gè)數(shù)組,而數(shù)組名其實(shí)是指向數(shù)組首元素的指針,arg1既然是指向str1[0]這個(gè)一維數(shù)組的指針,而str1[0]本身其實(shí)就是指向這個(gè)一維數(shù)組的指針,也就是說(shuō)arg1其實(shí)就是str1[0],因此cmp2能夠正常工作
1 (gdb) p &str1[0]
2 $3 = (char (*)[8]) 0xbffff2cc
3 (gdb) p &str1[0][0]
4 $4 = 0xbffff2cc "java"
5 (gdb) p arg1
6 $5 = (const void *) 0xbffff2cc
7 (gdb) p (char *)arg1
8 $6 = 0xbffff2cc "java"
額...貌似越說(shuō)越復(fù)雜的樣子,不過(guò)這是我理解的過(guò)程,見諒...