将指针转换为指向void指针的指针

时间:2012-11-05 03:20:26

标签: c void-pointers

当我学习使用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 */
    }

3 个答案:

答案 0 :(得分:2)

你的问题看起来有点模糊,但无论如何我都会试一试。要回答如何,您可以通过简单转换将任何指针类型转换为C中的任何其他指针类型。要回答为什么,那就是C的定义方式。

qsort()函数需要具有给定原型(带有const void *)参数的函数。这是因为qsort()不知道您正在排序的实际数据类型,并且必须使用一致的函数原型进行比较回调。您的比较回调负责将const void *参数转换为指向数组中实际类型的指针,例如const char **

答案 1 :(得分:2)

您提供的示例正在设置为要求qsort()对char指针数组(char *)进行排序。您提供的这个比较器会给出算法所需的每对“项目”,按地址。两个char指针。地址qsort()使用的地址基于您提供的根地址,每个“项目”添加大小字节数。由于每个“item”都是char *,因此每个项目的大小实际上是指针的大小。

我已经修改了比较器以演示正在比较的内容,以及传入的地址是什么。您将看到它们都是包含所有char * s的数组基址的增量。

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

答案 2 :(得分:0)

更不可视化的一个:

int cstring_cmp(const void *a, const void *b){
    return -strcasecmp((char *)(*((char **)a)), (char *)(*((char **)b)));
}

但是你可以看到,abchar **,他们被解除引用并成为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或虚拟)字节的指针。