Swapping 2 string pointers with a function whose parameters are void ** - c

The following code doesn't compile:
void swap(void **p, void **q) {
void *tmp;
tmp = *p;
*p = *q;
*q = tmp;
}
int main(void) {
char *s[] = {"help" , "please"};
swap(&s[0], &s[1]);
return 0;
}
While this code compiles and runs just fine:
void swap(void **p, void **q) {
void *tmp;
tmp = *p;
*p = *q;
*q = tmp;
}
int main(void) {
char *s[] = {"help" , "please"};
swap((void **) &s[0], (void **) &s[1]);
return 0;
}
Why is the casting necessary ?

Yeah, so in addition to the already existing answers that point out that void ** is not the same as char **: your code invokes undefined behavior because of the incompatible pointer types. Here's what you actually want:
void swap(void *p1, void *p2, size_t size)
{
unsigned char buf[size];
memcpy(buf, p1, size);
memcpy(p1, p2, size);
memcpy(p2, buf, size);
}
And call it like this:
const char *s[] = { "help", "please" }; // also note the use of `const' for string literals
swap(&s[0], &s[1], sizeof(s[0]));

You have incompatible pointer assignment error in first code. In C type of a string literal is char[N] Where N is number of chars. Note in most of expressions char[N] easily decays into char*
According to your declaration char *s[] = {"help" , "please"}; type of s[i] is char* (actaully char[N] decayed into char*).
When you pass &s[i] then you are passing char** that is incompatible with void**. Second code works because you typecast into void** in function calling.
void* can be assigned any address type but its void** that has to be assigned address of void* type variable.
If you only having array of strings then in first version of swap function you can replace void by char then you can all without typecast.

The casting makes the example compile because of what you are passing the function.
char *var[]; is in many ways the same as char **var;
With that being said, you are passing the function a reference/address one of the members of the array (s[0]).
Another more prominent issue, is that the function accepts void pointers, and is passed character pointers (without the casting).

Related

Pointer to function Prototype

i am trying to figure out what those prototypes mean
1.int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
2.int* (*fpData[2])(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (* fpCalculation[3]) (const char *));
3.int* (*(*fpData)(const char *))(int (*paIndex)[3] ,
int (* fpMsg) (const char *),
int (* fpCalculation[3]) (const char *));
First you should find actual variable which is being declared. In all 3 examples this is fpData. Then you should start to read declaration staring from this variable moving from inside to outside.
So, let us begin with first example. We see fpData, so we say "fpData is...", then we see "*" before "fpData", so we say "fpData is pointer to...", then we see function type declaration outside of *fpData, so we say "fpData is pointer to function...". Then we should read types of arguments and result of this function.
Well, you can read types for all 3 arguments without problems. They are:
"paIndex is pointer to array of length 3 of ints"
"fpMsg is pointer to function from const char * to int"
"fpCalculation is array of length 3 of pointers to function from const char * to int"
In the last argument you should note that [3] has the higher priority than "*". I mean that while reading declaration from inside to outside you should read first array and then pointer. I. e. int *a[3] is "a is array of length 3 of pointers of int" and not "pointer to array".
Assuming all this I think you can read 2nd declaration without problems.
Now you should learn this: type of function result is written outside (i. e. BEFORE AND AFTER) of everything else.
Let us consider this:
char (*(*fp)(int))(double)
What this means? Well let's start reading, "fp is pointer to function which takes int and returns... what?" Well, we already have read (*fp)(int) part. Now we want to read everything else. And we want to understand what is result type of function we already read. And now we should note that result of function is the thing which is written OUTSIDE (i. e. BEFORE and AFTER) of everything else, i. e. outside of what we already read.
So, we have read (*fp)(int). Everything else, i. e. char (*XXX)(double) is return type for function we already read. So, well, let's continue reading. Finally we will get this:
"fp is pointer to function which gets int and returns pointer to function which gets double and returns char".
Now you can read 3rd declaration without problems
The C gibberish ↔ English link that chux posted still looks like gibberish to
me. So I'll try to sound more human:
int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
This declares a function pointer fpData that returns a pointer to int. The
function takes 3 variables of the following types:
paIndex is a pointer to an int array of dimension 3. This can be used for
example when you have this:
void bar(int (*paIndex)[3])
{
}
void foo(void)
{
int fields[5][3] = { {1,1,1}, ... };
bar(fields);
}
fpMsg is a function pointer that returns an int. The function takes one
arguments only, a const char* (a string basically).
fpCalculation is an array of dimension 3 of function pointers that return
int. The functions take on argument only: a const char*.
This is a beast of a function pointer, it works in an evironment like this:
#include <stdio.h>
int msg(const char *name)
{
printf("msg: %s\n", name);
return 0;
}
int abc1(const char *name)
{
printf("abc1: %s\n", name);
return 0;
}
int abc2(const char *name)
{
printf("abc2: %s\n", name);
return 0;
}
int *scary_function(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *))
{
fpMsg("fpMsg");
fpCalculation[0]("fpCalculation0");
fpCalculation[1]("fpCalculation1");
fpCalculation[2]("fpCalculation2");
for(int i = 0; i < 4; ++i)
{
for(int j = 0; j < 3; ++j)
{
printf("%-3d ", paIndex[i][j]);
}
puts("");
}
return NULL;
}
void foo(void)
{
int matrix[4][3] = { {1,2,3}, {4,5,6}, {7,8,9}, {10,11,12} };
int (*fpcalcs[3])(const char*) = { msg, abc1, abc2 };
int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
fpData = scary_function;
// calling the function through the function pointer
fpData(matrix, msg, fpcalcs);
}
int main(void)
{
foo();
return 0;
}
The output of this is
msg: fpMsg
msg: fpCalculation0
abc1: fpCalculation1
abc2: fpCalculation2
1 2 3
4 5 6
7 8 9
10 11 12
So I've explained in detail how to parse the declaration of these function
pointers. Now try understanding the other 2 yourself, if you still have problems,
post a comment.
1.int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *), int (*fpCalculation[3]) (const char *));
Here, fpdata is pointer to a function which takes three arguments and returns a pointer to an integer. The arguments are as follows:
pointer to 3 elements integer array,
pointer to a function which takes const char pointer as an argument and return type int,
array of 3 function pointers and each function takes const char pointer as an argument and return type is int
2.int* (*fpData[2])(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));
In this case, fpdata is array of 2 function pointers, and each function takes three arguments -
pointer to 3 elements integer array,
pointer to a function which takes const char pointer as an argument and return type int,
array of 3 function pointers and each function takes const char pointer as an argument and return type is int
The return type is a pointer to an integer
3.int* (*(*fpData)(const char *))(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));
Finally, fpdata is a pointer to a function which takes three arguments -
pointer to 3 elements integer array,
pointer to a function which takes const char pointer as an argument and return type int,
array of 3 function pointers and each function takes const char pointer as an argument and return type is int
The return type is a function pointer which takes const char pointer as argument and return type is pointer to an integer.
int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
it is function prototype declaration.
Where fpData is a function name, function that takes three arguments:
int (*paIndex)[3]
int (* fpMsg) (const char *)
int (*fpCalculation[3]) (const char *)
…and returns a function pointer [pointer to a function that take no argument but returns pointer to an integer].
Details :: Given function can be written as below
typedef int* (*ret_func_ptr) ();
ret_func_ptr (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));

Generic pointer to pointer

I understand that according to standard void * is generic pointer, and void ** is not. So, in my program, I am trying to cast void * and not directly type cast void ** but I am not getting expected results. I think I am missing something very basic in here.
#include <stdio.h>
void check(void **p)
{
printf("value: %d\n", *(int *)*p);
}
int main()
{
int a[] = {6,2,5,1,8};
int *p;
p = a;
void **val;
val = (void *)p;
check(val);
return 0;
}
I have a void ** pointer val, which is pointing to int * but casted to void *. I pass this to function check, which is expecting void **. In my printf, I first cast *p (which is void *) to int * and then derefernce it. I get some random value. Am I missing something here?
The problem is in the call to printf:
printf("value: %d\n", *(int *)*p);
In main, val (which is a void **) contains the contents of a int *. This is then passed to check, where is now called p. This needs to be casted to an int * to read correctly:
printf("value: %d\n", *(int *)p);
Of course, since a void ** is not a generic pointer, it doesn't make much sense to do this. Best to get rid of the extra level of indirection which isn't being used anyway:
void check(void *p)
{
printf("value: %d\n", *(int *)p);
}
int main()
{
int a[] = {6,2,5,1,8};
int *p;
p = a;
void *val;
val = p;
check(val);
return 0;
}
Change val = &p; to val = p;
Probably it was a kind of "typo" since you had already passed the value once correctly and later also dereferenced it.
EDIT:
You can change: val = (void *)p; to val = (void *)&p;
As you said yourself, void** is not a generic pointer. It is a pointer that point to an object of type void*, and nothing else. Using a cast to point it at an object of type int* is type punning.
In your case, you should simply cast your int* to void*, and back to int* again. No void** involved.

getting at pointers in an array of struct passed as a void*

I have a function with a signature like qsort:
const char* get_str(int i, const void *base, size_t nmemb, size_t size);
I am passed arrays of pointers to const char*, or arrays of structs whose first field is a pointer to const char*.
What casts do I need to do to extract that pointer in the array element i?
I have tried casting the base as an array of char itself, so I can advance to the right element:
return *(const char**)(((const char*)base)[i * size]);
But the compiler is complaining: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
It looks like you want to implement a type or identification sytem for structs like so:
#include <stdlib.h>
#include <stdio.h>
struct a {
const char *id;
int x;
};
struct b {
const char *id;
double d;
};
union any {
struct a a;
struct b b;
};
int main()
{
struct a a[] = {{"one", 1}, {"two", 2}, {"three", 3}};
struct b b[] = {{"pi", 3.1415}, {"e", 2.71}};
union any any[3];
any[0].a = a[0];
any[1].b = b[0];
any[2].a = a[1];
puts(get_str(1, a, 3, sizeof(*a)));
puts(get_str(1, b, 2, sizeof(*b)));
puts(get_str(1, any, 3, sizeof(*any)));
return 0;
}
In this case, the following works:
const char* get_str(int i, const void *base, size_t nmemb, size_t size)
{
const char *p = base;
const char **pp = (const char**) (p + i * size);
return *pp;
}
This can be written in one line as:
const char* get_str(int i, const void *base, size_t nmemb, size_t size)
{
return *(const char**) ((const char *) base + i * size);
}
But I think that the detour via void pointers is not necessary. You can do the address calculations with the typed array:
puts(*(const char **) (&a[1]));
puts(*(const char **) (&b[1]));
puts(*(const char **) (&any[1]));
If you wrap that in a function:
const char *get_str(const void *str)
{
return *(const char **) str;
}
you get:
puts(get_str(&a[1]));
puts(get_str(&b[1]));
puts(get_str(any + 1));
which is more readable than the qsortish syntax in my opinion.
This works, because you acces only one element at a known position. The functions bsort and qsort, however, can't use this technique, because they have to access the array at several indices and hence must be able to do the index calculation themselves.
Find me (well, "yet another" but suppose this parentheses never existed!) a bug in that compiler and I give you a free cookie!
The compiler is right. This
*(const char**)(((const char*)base)[i * size]);
Will type-compile to something like (syntax: expresion -> type)...
base -> const void*
(const char*)base -> (const char*)const void*
(((const char*)base)[i * size]) -> *(const char*)const void* -> const char // Here's the problem!
(const char**)(((const char*)base)[i * size]) -> (const char**)const char // Now, this is *not* good...
*(const char**)(((const char*)base)[i * size]) -> *(const char**)const char -> const char* // Well, we have now just perfectly dereferenced '~'...
Not very sane, isn't it?*
BTW: You don't give us enough information for me to provide a full solution to your problem. What are those structs you talk about?
Edit: May this help you (written according to comments)?
*(const char**)&(((const unsigned char*)base)[size * i])

Passing to void** instead void* makes the compiler complain about types, why?

I don't understand why the compiler warn me about passing an incompatible pointer type in this code: (in this context what are the difference between void * and void **) (I don't know if this make some difference but I am using gnu99 C version)
void someFunc(void ** foo) {
printf("%s\n", *foo);
}
int main() {
char * text = "some text";
someFunc(&text);
return 0;
}
and in this not
void someFunc(void * foo) {
printf("%s\n", foo);
}
int main() {
char * text = "some text";
someFunc(text);
return 0;
}
Thanks in advance
void * is a type that is implicitly convertible to and from any object pointer type. void ** isn't - so while you can assign a char * to a void *, you can not do the same with char ** and void **.
The reason is that they are incompatible types: char ** points to a char *, void ** points to a void *, so their base types don't match.
To fix your code in the second example, you can do one of the following:
// Solution A, preferred:
void someFunc(char * foo) {
printf("%s\n", foo);
}
int main() {
char * text = "some text";
someFunc(text);
return 0;
}
In A you are telling the compiler that the parameter being passed is a pointer to a char.
I haven't tried solution B, should work but why use voids if they are NOT absolutely necessary.
// Solution B, should work but a purist might object:
void someFunc(void * foo) {
printf("%s\n", foo);
}
int main() {
char * text = "some text";
someFunc( (void *) text);
return 0;
}
In this question there is no obvious reason to use a double ptr, so Solution A for your second example is probably the way to go.

convert pointer to pointer to void pointer

When I'm learning to use qsort to sort an array of string, there is a question puzzled me.
For example, to sort the following s
char *s[] = {
"Amit",
"Garima",
"Gaurav",
"Vaibhav"
};
To use the qsort, you must provide a comparison function like the
following function cstring_cmp I guess in the qsort function, the type of parameter to be passed to the function cstring_cmp is char**. How to convert a char** to a void*? Why can we convert a char** to a 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 */
}
Your question seems a bit vague but I'll give it a go anyway. To answer how, you can convert any pointer type to any other pointer type in C by simply casting. To answer why, well that's how C is defined.
The qsort() function requires a function with the given prototype (with const void *) parameters. This is because qsort() is unaware of the actual data type you are sorting, and must use a consistent function prototype for the comparison callback. Your comparison callback is responsible for converting the const void * parameters to pointers to the actual types in your array, in your case const char **.
The example you provide is being setup to ask qsort() to sort an array of char pointers (char *). This comparator you're providing is given each 'pair' of items the algorithm needs, by address. two char pointers. the address qsort() uses is based on the root address you give it, adding size-bytes per "item". Since each "item" is a char*, the size of each item is, in fact, the size of a pointer.
I've modified the comparator to demonstrate what is being compared, and what the addresses are that are being passed in. you will see they are all increments off the base address of the array containing all the 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;
}
produces the following output:
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
A even less visualized one:
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
It is legal to cast any pointer to char * or void * because void * means a pointer to a memory (RAM or virtual) byte.

Resources