簡體   English   中英

將指針轉換為指向void指針的指針

[英]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)));
}

但你可以看到, 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或虛擬)字節的指針。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM