0

I have observed that using some of the predefined functions, I should cast my data to void* and then pass it to the function. This is simple to understand.

My question is what is the difference between these two casts:

  1. (void **)&a
  2. (void*)a

Which one of them should I use and what is the difference?

muradin
  • 1,249
  • 2
  • 14
  • 34
  • 6
    They're totally different. Which one you should use depends entirely on what the goal is. Re: "I'm going to learn C" - I suggest [first learning C](http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list), and then posting questions ;) (rather than the other way around) – Oliver Charlesworth Dec 03 '13 at 17:05
  • Wait, you cast your data to `void` and then pass to the function? You can't do that. – Shahbaz Dec 03 '13 at 18:26

2 Answers2

1

You wrote, "this is simple to understand". Clearly it is not. Firstly, you are not casting the data, nothing is happening to the data. Secondly, what you pass to the function with a vs &a is totally different. A void pointer is simply a reference to some data. The underlying data type is unknown (to the compiler). Due to this fact, you cannot perform pointer arithmetic for example.

Let's say you malloc() a chunk of memory to store some data and the pointer returned is the value 0x2020 and is assigned to x. Now let's say x is on a region of the stack at memory location 0x1000. This means x is 0x2020. *x is the data you put inside that malloc'd region. Now the important part.. &x is 0x1000 which is the memory address of x and in our hypothetical case, this is on the stack. The following example demonstrates a bit of void * and void **. It is just a quick sample and not the correct way to do anything except demonstrate the concept.

#include <stdio.h>

struct t1 { int a; };
struct t2 { int b; };

int testvppa(void **pp){
    void *p = *pp;
    struct t1 * pt = (struct t1 *)p; // need to cast in order to de-reference
    return pt->a;
}
int testvppb(void **pp){
    void *p = *pp;
    struct t2 * pt = (struct t2 *)p; // need to cast in order to de-reference
    return pt->b;
}
int testvp(void *p, int which){
    if (which == 1)
    {
        return testvppa(&p);
    }
    else{
        return testvppb(&p);
    }
}

int main(){
    struct t1 stuffa = { 123 };
    struct t2 stuffb = { 456 };
    void * vp;

   printf("stuffa: {%d} @ %p\n", stuffa.a, &stuffa);
   printf("stuffb: {%d} @ %p\n", stuffb.b, &stuffb);

   vp = &stuffa;
   printf("vp: %p test: %d\n", vp, testvp(vp,1));

   vp = &stuffb;
   printf("vp: %p test: %d\n", vp, testvp(vp,2));
   return 0;
}

Running on my machine has the following results: (Note the address of the pointers will change but values 123, and 456 will be the same.)

stuffa: {123} @ 0x7fff28116db0
stuffb: {456} @ 0x7fff28116dc0
vp: 0x7fff28116db0 test: 123
vp: 0x7fff28116dc0 test: 456

There's a good chance my answer will be more confusing than enlightening. This is why the actual correct answer to your question is exactly what Oli Charlesworth said in his comment: "I suggest first learning C, and then posting questions"

doog abides
  • 2,270
  • 16
  • 13
0

The first one passes an address to your pointer (pointer to pointer) to the function. By de-referencing it, the function should be able to return a pointer to you, as an output parameter.

The second can only be used as an input parameter.

example (in C code):

struct stuff { int t; };

void allocate_stuff(void **allocated) {
    struct stuff *opaque = malloc(sizeof(*opaque));
    *allocated = opaque; /* the dereferencing I mentioned - sets "output" value */
}

void deallocate_stuff(void *allocated) {
    free(allocated);
}

void * handle = NULL;
allocate_stuff(&handle); /* can return pointer due to */
deallocate_stuff(opaque);

Edit: to understand why the first is an "output parameter" you could look at formal/actual parameter definitions.

utnapistim
  • 26,809
  • 3
  • 46
  • 82
  • 1. [Don't cast the result of `malloc`](http://stackoverflow.com/a/605858/249237) 2. In `deallocate_stuff` the cast isn't necessary (`void *` gets promoted automatically). 3. The OP didn't mention C++, nor is it in the tags so you could leave out the bit about C++ (it's best to keep the two languages strictly separate, especially for someone who's still learning) – Kninnug Dec 03 '13 at 17:17
  • 4. Use `sizeof *opaque` instead of `sizeof(struct stuff)`. That way, you won't be repeating the type many times and you'd have an easier time changing the type in the future. – Shahbaz Dec 03 '13 at 18:28