Convert pointer to pointer to void pointer

When I learn to use qsort to sort an array of strings, a question arises that puzzled me. For example, to sort the following s

  char *s[] = { "Amit", "Garima", "Gaurav", "Vaibhav" }; 

To use qsort, you must provide a comparison function, such as the following cstring_cmp function cstring_cmp I believe that in the qsort function, the type of parameter to be passed to the cstring_cmp function is char** . How to convert a char** to void* ? Why can we convert a char** to 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 */ } 
+4
source share
3 answers

Your question seems a little vague, but I will give it to him anyway. To answer this question, you can convert any type of pointer to any other type of pointer in C in a simple way. To answer why, it’s good that how C is defined.

The qsort() function requires a function with this prototype (with const void * parameters). This is because qsort() not aware of the actual data type that you are sorting, and must use a prototype of a consistent function to call a comparison callback. The comparison callback is responsible for converting const void * parameters to pointers to the actual types in your array, in your case const char ** .

+2
source

The example you provide is customizable to ask qsort() sort an array of char (char *) pointers. This comparator to which you provide is provided to each "pair" of elements that the algorithm requires at an address . two char pointers. qsort() uses the address based on the root address that you give it, adding size-bytes to the "element". Since each "element" is a char *, the size of each element is, in fact, the size of the pointer.

I modified the comparator to demonstrate what is being compared and what addresses are being transmitted. You will see that they all increase from the base address of the array containing all 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; } 

outputs the following result:

 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
source

Even less visualized:

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

But you can see, a and b are char ** , and they are dereferenced and become char * and passed to 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; } 

Output:

 Vaibhav Gaurav Garima Amit 

Any pointer to char * or void * complete, because void * means a pointer to a memory byte (RAM or virtual).

0
source

Source: https://habr.com/ru/post/1444033/


All Articles