指针转换为与qsort一起使用

yas*_*sar 4 c pointers casting

从我正在阅读的书中复制的代码片段手:

/* scmp: string compare of *p1 and *p2 */
int scmp(const void *p1, const void *p2)
{
        char *v1, *v2;
        v1 = *(char **) p1; 
        v2 = *(char **) p2; 

        return strcmp(v1, v2);
}
Run Code Online (Sandbox Code Playgroud)

此函数与qsort一起使用以对字符串数组进行排序.我不明白的一点是,为什么v1 = *(char **) p1;不是只是v1 = (char *) p1;或者不会这样做; v1 = p1;?我想编译器应该自动对该分配进行类型转换.或者甚至,考虑一下:

/* scmp: string compare of *p1 and *p2 */
int scmp(const void *p1, const void *p2)
{
        return strcmp(p1, p2);
}
Run Code Online (Sandbox Code Playgroud)

我认为(我可能是非常错误)编译器应该强制转换p1p2char *,因为它是什么样strcmp(char *, char *)的期望.

总结一下,问题是为什么v1 = *(char **) p1

Mat*_*lia 7

qsort向比较函数传递指向它必须比较的元素的指针; 因为在C中没有模板,所以这个指针只是被粗暴地强制转换为const void *(void *在C中只是意味着"这是某种指针",并且要对它做一些事情,你必须将它转换回它的实际类型).

现在,如果要对字符串数组进行排序,则必须比较的每个元素都是a char *; 但是qsort向比较函数传递一个指向每个元素的指针,所以你scmp接收到的实际上是一个char **(指向字符串第一个字符的指针),转换为a,const void *因为比较函数的签名是这样的.

因此,为了得到你的char *,你首先要将参数转换为它们的实际类型(char **),然后取消引用这个指针以获得char *你想要比较的实际值.

(尽管从const-correctness的观点来看,它会更加正确const char **)