假设我有一个指向C中char的指针数组:
char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };
我想用qsort对这个数组进行排序:
qsort(data, 5, sizeof(char *), compare_function);
我无法使用比较函数。由于某些原因,它无法工作:
int compare_function(const void *name1, const void *name2)
{
const char *name1_ = (const char *)name1;
const char *name2_ = (const char *)name2;
return strcmp(name1_, name2_);
}
我做了大量的搜索,发现我必须在qsort中使用**
:
int compare_function(const void *name1, const void *name2)
{
const char *name1_ = *(const char **)name1;
const char *name2_ = *(const char **)name2;
return strcmp(name1_, name2_);
}
这很管用。
有谁能解释一下*(const char **)name1
在这个函数中的用法吗?我一点也不明白。为什么要用双指针?为什么我原来的函数不起作用?
谢了博达·赛多。
9条答案
按热度按时间5q4ezhmt1#
如果这能帮助你理清思路的话,那么你应该在比较器中将指针强制转换为与你传递给
qsort
的数据指针的原始类型相同的类型(qsort文档称之为base
),但是对于泛型的qsort
来说,它只是将所有东西都作为void*
来处理,而不管它“实际上”是什么。所以,如果你要对一个int数组排序,那么你需要传入一个
int*
(转换成void*
)。qsort会给予两个指向比较器的void*
指针,你可以将其转换成int*
,然后解引用得到你实际比较的int
值。现在将
int
替换为char*
:如果你正在排序一个
char*
数组,那么你将传入一个char**
(转换为void*
)。qsort将给予两个void*
指针给比较器,你将其转换为char**
,并解引用以获得你实际比较的char*
值。在本例中,由于使用的是数组,传入的
char**
是char*
数组“衰减”到指向其第一个元素的指针的结果。由于第一个元素是char*
,因此指向它的指针是char**
。8tntrjer2#
假设您的数据是
double data[5]
。比较方法将接收指向元素(double)的指针(double*,作为void* 传递)。
现在再次用char* 替换double。
wa7juj8i3#
qsort
足够通用,可以对指针以外的数组进行排序。这就是size参数存在的原因。它不能将数组元素直接传递给比较函数,因为它在编译时不知道它们有多大。因此它传递指针。在您的情况下,您将获得指向char *
、char **
的指针。aiazj4mn4#
比较函数获取指向数组中要排序的对象类型的指针,因为数组包含
char *
,所以比较函数获取指向char *
(又名char **
)的指针。332nm8kg5#
也许给予你一个我的代码示例会更容易些。我正在尝试对一个TreeNode数组进行排序,我的比较器的前几行如下所示:
然后,使用t1和t2进行比较。
wswtfjt76#
从
man qsort
开始:所以听起来比较函数得到了指向数组元素的指针,现在指向
char *
的指针就是char **
(即指向字符指针的指针)。mbyulnm07#
char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };
是一条语句,它要求编译器提供一个长度为5的字符指针数组。您已经将这些指针初始化为字符串文字,但对于编译器来说,它仍然是一个5个指针的数组。
当您将该数组传递给
qsort
时,指针数组将衰减为指向第一个元素的指针,这与C数组参数传递规则一致。因此,必须先处理一个级别的间接寻址,然后才能访问包含常量的实际字符数组。
epfja78i8#
@bodacydo这里是一个程序,可以解释其他程序员试图传达什么,但这将是在“整数”的上下文中
pdkcd3nj9#
qsort()
传递了一个指向用户定义的比较函数的指针,并且由于您有一个char *
(指向字符数组的指针),因此您的比较函数应该从指针解引用到指针,因此是char **
。