I'm trying to figure out how to "transform" strings (char*) to void* and viceversa. When I execute this my output is just the first printf and ignores the second one, it doesn't even write "after = "
PS This little program is just to understand, I know i could actually use swap(&s[0],&s[1]). I need to know how to properly cast a void pointer into an array of strings. I'm working on a uni project where I need to create my own quick_sort algorythm and I need the swap function inside of it to work with void pointers.
#include <stdio.h>
#include <stdlib.h>
static void swap(char** x,char** y);
static void swap(char** x,char** y){
char* temp=*x;
*x=*y;
*y=temp;
}
int main()
{
char* s[2];
s[0]="weee";
s[1]="yooo";
void* array=s;
printf("before %s %s\n",s[0],s[1]);
swap((&array)[0],(&array)[1]);
printf("after = %s %s",(char*)array,(char*)array);
return 0;
}
I think I'm missing something big Thanks in advance :D
CodePudding user response:
In this declaration the array s
used as an initializer is implicitly converted to a pointer to its first element of the type char **
.
void* array = s;
In the call of the function swap
swap((&array)[0],(&array)[1]);
the first argument can be the pointer array
itself that will be implicitly casted to the pointer type of the corresponding parameter
swap( array, (&array)[1]);
But you need to correctly pass the second argument. To do this you need to cast the pointer array
explicitly like
swap( array, ( char ** )array 1 );
In the call of printf
you need also correctly to supply argument expressions.
Here is your updated program
#include <stdio.h>
static void swap(char** x,char** y);
static void swap(char** x,char** y){
char* temp=*x;
*x=*y;
*y=temp;
}
int main()
{
char* s[2];
s[0]="weee";
s[1]="yooo";
void* array=s;
printf("before %s %s\n",s[0],s[1]);
swap( array, ( char ** )array 1 );
printf("after = %s %s", *(char**)array, ( (char**)array )[1]);
return 0;
}
The program output is
before weee yooo
after = yooo weee
CodePudding user response:
void *array = s;
declares array
to be a void *
. Then &array
is the address of that void *
, so &array[1]
would access a void *
after it. But there is no void *
after it, since void *array
defines a single void *
.
array
could be properly defined to alias s
with char **array = s;
, after which swap(&array[0], &array[1]);
would work as desired.
If you define array as void **array = (void **) s;
, then swap(&array[0], &array[1]);
will produce diagnostic messages because the types are wrong. You could use swap((char **) &array[0], (char **) &array[1]);
.
Then, if you print the strings with printf("after = %s %s", array[0], array[1]);
, this will work, although it is not entirely proper code. Using array[0]
as an argument passes a void *
where printf
is expecting a char *
for the %s
. However, the C standard guarantees that void *
and char *
have the same representation (encode their values using bytes in memory in the same way), and it further says (in a non-normative note) that this is intended to imply interchangeability as arguments to functions.
CodePudding user response:
The void*
doesn't seem to fulfil any particular purpose here, just swap the pointers: swap(&s[0],&s[1]);
.
You could also do this:
char** ptr = &s[0];
printf("before %s %s\n",ptr[0],ptr[1]);
swap(&ptr[0],&ptr[1]);
printf("after = %s %s",ptr[0],ptr[1]);
If you for reasons unknown insist on using void*
then note that as your code stands, it points at the first char*
in your array of char*
. However, it isn't possible to perform pointer arithmetic on void*
since that would entail knowing how large a "void
" is. The void*
doesn't know that it points at an array of pointers. Therefore array[i]
is nonsense.
Also, the void*
are set to point at char*
so you simply cannot pass it to a function expecting a char**
. You'd have to rewrite the whole program in a needlessly obfuscated way, so just abandon that idea.