如何在C中输入指向char的指针数组?

假设我在C中有一个指向char的指针数组:

char *data[5] = { "boda", "cydo", "washington", "dc", "obama" }; 

我希望使用qsort对这个数组进行排序:

 qsort(data, 5, sizeof(char *), compare_function); 

我无法想出比较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吗? 我根本不明白。 为什么双指针? 为什么我的原始function不起作用?

谢谢,Boda Cydo。

如果它有助于将事情直接放在头脑中,那么应该在比较器中投射指针的类型与传递给qsort的数据指针的原始类型相同(qsort docs调用base )。 但是对于qsort是通用的,它只是将所有内容都处理为void* ,而不管它是什么“真正”。

所以,如果你正在排序一个int数组,那么你将传入一个int* (转换为void* )。 qsort将返回两个指向比较器的void*指针,您将其转换为int* ,并取消引用以获取实际比较的int值。

现在用char*替换int

如果你要排序一个char*数组,那么你将传入一个char** (转换为void* )。 qsort将返回两个指向比较器的void*指针,将其转换为char** ,并取消引用以获取实际比较的char*值。

在您的示例中,因为您正在使用数组,所以传入的char**char*数组“衰减”到指向其第一个元素的指针的结果。 由于第一个元素是char* ,因此指向它的指针是char**

想象一下,你的数据是double data[5]

您的比较方法将接收指针(double *,传递为void *)到元素(double)。
现在再次用char *替换double。

qsort足以排序由除指针之外的其他东西组成的数组。 这就是尺寸参数存在的原因。 它不能直接将数组元素传递给比较函数,因为它在编译时不知道它们有多大。 因此它传递指针。 在你的情况下,你得到指向char *char **指针。

比较函数获取指向要排序的数组中对象类型的指针。 由于数组包含char * ,因此比较函数会将指针指向char * ,即char **

来自man qsort

 The contents of the array are sorted in ascending order according to a comparison function pointed to by compar, which is called with two arguments that **point** to the objects being compared. 

所以听起来比较函数获取指向数组元素的指针。 现在,指向char *的指针是char ** (即指向char **指针的指针)。

char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };

是一个声明,要求编译器提供一个大小为5的字符指针数组。 你已经初始化了那些指向字符串文字的指针,但是对于编译器来说,它仍然是一个包含五个指针的数组。

当您将该数组传递给qsort ,指针数组会根据C数组参数传递规则衰减为指向第一个元素的指针。

因此,在获得包含常量的实际字符数组之前,必须先处理一个间接层。

@bodacydo这里有一个程序,可以解释其他程序员试图传达的内容,但这将是“整数”的背景

 #include  int main() { int i , j; int *x[2] = {&i, &j}; i = 10; j = 20; printf("in main() address of i = %p, address of j = %p \r\n", &i, &j); fun(x); fun(x + 1); return 0; } void fun(int **ptr) { printf("value(it would be an address) of decayed element received = %p, double dereferenced value is %d \r\n",*ptr, **ptr); printf("the decayed value can also be printed as *(int **)ptr = %p \r\n", *(int **)ptr ); }