void *ptr;
int num = 13;
char c = 'q';
Without using struct, is it possible to reference 'num' and 'c' and then deference from the void pointer?
void *ptr;
int num = 13;
char c = 'q';
Without using struct, is it possible to reference 'num' and 'c' and then deference from the void pointer?
Without using struct, is it possible to reference 'num' and 'c' and then deference from the void pointer?
Yes, it is..
Consider this
void *ptr;
int num = 13;
char c = 'q';
ptr = #
printf("%d ", *((int *)ptr);
ptr = &c;
printf("%c ", *((char *)ptr);
After your rather vague update, I think you're trying to ask whether or not it's possible to make ptr
hold the memory address of num
or c
and change the value stored within that memory. The answer is: Yes, but the resulting code looks disgusting:
#include <stdio.h>
int main ( void )
{
char c = 'a';
int i = 123;
void *ptr;
*(int *)(ptr = &i) += c;
printf("%d\n", i);
return 0;
}
Let's just read through the "voodoo magic": *(int *)(ptr = &i) += c;
(ptr = &i)
: this is the starting point. I'm assigning the address if the int i
variable to ptr
. Because an assignment expression in C evaluates to the new value of the left member (ptr
), this expression resolves to the address of i
.*(int *)
: I'm casting ptr
, which has now been assigned to an int *
, and I dereference it, effectively allowing me to write to the memory that ptr
points to.+= c;
: I'm adding the value of c
(char
is an integer type in C remember) to the value in memoryThe net result is that i
was now set to 220.
Now that you've seen this kind of madness:
You mentioned memcpy
a couple of times. I think what you were trying to do here was either something like this:
memcpy(&num, &c, sizeof c);//sizeof c == 1, always
Which is perfectly valid (move 1 byte from the memory that stores c
, and copy it to num
). It is rather silly, though. memcpy
is mainly used to copy arrays, data structures or heap memory. num
is an int, c
is a char
.
char
is an integer type in CSo instead of calling functions, and generally making life a lot more complicated than it has to be:
num = c;
will do exactly what you want it to do, it's the cleanest, fastest, and easiest solution, and therefore: it's the best.
The standard states that void *
(a void pointer) can be safely converted into any other pointer type and back again. This means that a pointer to any type can be assigned to a void pointer, without problems. So to the answer to your question is yes:
ptr = &c;
ptr = #
Are both valid things to do. However, the standard does not allow a void pointer to be dereferenced. You have to cast to a specific type in order to get the value of the memory it points to:
ptr = &c;
printf("%c\n", *(char *)ptr);
ptr = #
printf("%d\n", *(int *)ptr);
Which in turn rather defeats the point of explicitly declaring a variable of the type void *
, because you can only safely use it if you know what type to cast it to. Notable exceptions here are of course function arguments...
Often libraries will allow/require you to pass pointers to callback functions. A library can be used to connect to a resource of some kind, and once it's done its thing, you want your function to be invoked. It's not uncommon to want to have access to state in those kind of callbacks, something that can be easily done by passing a pointer to a block of memory.
As far as the library is concerned, that pointer is of an unknown type, so the library functions might look like this:
void some_external_lib_function(int (*callback)(int, void *), void *data);
Something you then call by doing this:
some_external_lib_function(
my_callback_function,
(void *) ptr_to_my_data
);
Without using struct, is it possible to reference 'num' and 'c' and then deference from the void pointer?
It is cleanly possible by introducing another variable:
int main(void)
{
void * vpa[2];
void * ptr = &vpa; /* &vpa evaluates to a void*(*)[2],
a pointer to an array of two pointers to void.*/
int num = 42;
char c = '6';
(*((void*(*)[2]) ptr))[0] = #
(*((void*(*)[2]) ptr))[1] = &c;
printf("num = %d, c = %c\n",
*((int*) ((*((void*(*)[2]) ptr))[0])),
*((char*) ((*((void*(*)[2]) ptr))[1]))
);
}
Result:
num = 42, c = 6
:-)