如何在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 ); }