[英]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.