-2
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?

Meehatpa
  • 349
  • 2
  • 10
  • I think I should add that reference and dereference together using one iteration, not separately. I understand memcpy should be used but unable to do it correctly. – Meehatpa Apr 18 '16 at 16:51
  • 1
    *I understand memcpy should be used but unable to do it correctly.* If you're having problems coding with `memcpy()`, using `void *` pointers to avoid `memcpy()` is like having problems with a lighter to start your barbecue fire, so you go get a flamethrower. It's not going to end well. – Andrew Henle Apr 18 '16 at 16:58
  • 1
    @AndrewHenle, sounds interesting, btw. Flamethrower barbeque - reminds me of Shishkebab from Fallout series. – SergeyA Apr 18 '16 at 17:09
  • @Meehatpa: I've added 2 updates to my insanely verbose answer: The second update uses `memcpy` and then goes on to explain why you really, really, really don't need to use it here. And even if you did, you wouldn't need to _declare_ a void pointer – Elias Van Ootegem Apr 18 '16 at 17:16

3 Answers3

1

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);
Praveen Talavar
  • 313
  • 1
  • 11
1

Update

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 memory

The net result is that i was now set to 220.

Now that you've seen this kind of madness:

Don't do this!

Update II

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 C

So 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 = &num;

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 = &num;
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
);
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • added more info about the question in comment – Meehatpa Apr 18 '16 at 16:54
  • @Meehatpa: do you mean: make `ptr` point to the location of `c` or `num` in memory, and reassign in one go? – Elias Van Ootegem Apr 18 '16 at 16:57
  • ptr to point num and then c and then retrieve those values again – Meehatpa Apr 18 '16 at 17:06
  • That's something you can't do in one go. You can't use a single pointer to access to different places in memory at the same time, not without ripping a whole in the fabric of space-time and creating a massive black hole at any rate. BTW, you mentioned `memcpy`. It's perfectly valid to pass the address of a variable to that function directly: `memcpy(&num, &c, 1);` will copy 1 byte (`sizeof c` is guaranteed to be 1) to the memory storing `num` – Elias Van Ootegem Apr 18 '16 at 17:10
  • @EliasVanOotegem: Many problems are solvable by adding another level of indirection. You might like to have look at my answer. – alk Apr 18 '16 at 17:36
  • @alk: I'm in no way contesting the fact that this problem _can_ be solved using indirection, but judging by the OP's comments, all he's actually trying to do, I think, is to assign the value of one variable to the other, regardless of type (char to int). It seems the OP thinks he has to go through a `void *` because of the different types, and thus use `memcpy`. I'm just saying that, if he wants to assign `c` to `num`, he's better of using a simple assignment... – Elias Van Ootegem Apr 19 '16 at 06:38
-1

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] = &num;
  (*((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

:-)

alk
  • 69,737
  • 10
  • 105
  • 255