[英]convert pointer to pointer to void pointer
当我学习使用qsort对字符串数组进行排序时,有一个问题困惑我。 例如,下面的排序s
char *s[] = {
"Amit",
"Garima",
"Gaurav",
"Vaibhav"
};
要使用qsort,你必须提供一个比较函数,如下面的函数cstring_cmp
我想在qsort函数中,要传递给函数cstring_cmp
的参数类型是char**
。 如何将char**
转换为void*
? 为什么我们可以将char**
转换为void*
?
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return -strcasecmp(*ia, *ib);
/* return the negative of the normal comparison */
}
你的问题看起来有点模糊,但无论如何我都会试一试。 要回答如何 ,您可以通过简单转换将任何指针类型转换为C中的任何其他指针类型。 要回答原因 ,那就是C的定义方式。
qsort()
函数需要一个具有给定原型(带有const void *
)参数的函数。 这是因为qsort()
不知道您正在排序的实际数据类型,并且必须使用一致的函数原型进行比较回调。 您的比较回调负责将const void *
参数转换为指向数组中实际类型的指针,在您的示例中为const char **
。
您提供的示例是设置为要求qsort()
对char指针数组(char *)进行排序。 您提供的这个比较器按地址给出算法所需的每对“项目”。 两个char指针。 qsort()
使用的地址是基于你给它的根地址,每个“item”添加size-bytes。 由于每个“item”都是char *,因此每个项目的大小实际上是指针的大小。
我已经修改了比较器以演示正在进行比较的内容,以及传入的地址是什么。您将看到它们都是包含所有char *的数组基址的增量。
char *mystrings[] =
{
"This",
"is",
"a",
"test",
"of",
"pointers",
"to",
"strings"
};
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
printf("%p:%s - %p:%s\n", a, *ia, b, *ib);
return -strcasecmp(*ia, *ib);
}
int main(int argc, char *argv[])
{
printf("Base address of our pointer array: %p\n\n", mystrings);
qsort(mystrings, sizeof(mystrings)/sizeof(mystrings[0]), sizeof(char*), cstring_cmp);
for (size_t i=0; i<sizeof(mystrings)/sizeof(mystrings[0]);i++)
printf("%s\n", mystrings[i]);
return 0;
}
产生以下输出:
Base address of our pointer array: 0x100006240
0x100006240:This - 0x100006260:of
0x100006260:of - 0x100006278:strings
0x100006240:This - 0x100006278:strings
0x100006248:is - 0x100006240:strings
0x100006278:This - 0x100006240:strings
0x100006250:a - 0x100006240:strings
0x100006270:to - 0x100006240:strings
0x100006258:test - 0x100006240:strings
0x100006260:of - 0x100006240:strings
0x100006268:pointers - 0x100006240:strings
0x100006260:of - 0x100006240:strings
0x100006240:test - 0x100006248:This
0x100006248:test - 0x100006250:to
0x100006240:This - 0x100006248:to
0x100006260:of - 0x100006268:pointers
0x100006268:of - 0x100006270:a
0x100006270:a - 0x100006278:is
0x100006268:of - 0x100006270:is
to
This
test
strings
pointers
of
is
a
一个更不可视化的:
int cstring_cmp(const void *a, const void *b){
return -strcasecmp((char *)(*((char **)a)), (char *)(*((char **)b)));
}
但你可以看到, a
和b
是char **
,它们被解除引用并成为char *
并传递给strcasecmp
。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int cstring_cmp(const void *a, const void *b){
return -strcasecmp((char *)(*((char **)a)), (char *)(*((char **)b)));
}
int main(){
char *s[] = { "Amit",
"Garima",
"Vaibhav",
"Gaurav"};
qsort(s, 4, sizeof(char *), cstring_cmp);
printf("%s\n%s\n%s\n%s\n", s[0], s[1], s[2], s[3]);
return 0;
}
输出:
Vaibhav
Gaurav
Garima
Amit
将任何指针转换为char *
或void *
是合法的,因为void *
表示指向内存(RAM或虚拟)字节的指针。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.