1

I did a function f which takes as input a (void*), convert it to a (int*) and print the value.

#include <stdlib.h>
#include <stdio.h>

void    f(void* p)
{
    int *pi = (int*)p;
    printf("%d\n", *pi);
}

int main()
{
    int x = 1;
    int *px = &x;
    void    *pv = (void*)px;
    f(pv);
    
    return 0;
}

Is it possible to implement a function:

void f2(void** pp);

such that it performs the "same" operations of the function f? My goal is to learn how to convert a (int*) to a (void**) and viceversa.


EDIT: error and warning of @tadman code (I did a mistake)

fvv.c: In function ‘f2’:
fvv.c:10:12: warning: initialization of ‘int *’ from incompatible pointer type ‘int **’ [-Wincompatible-pointer-types]
   10 |  int *pi = (int**)p;
      |            ^
fvv.c:12:17: error: invalid type argument of unary ‘*’ (have ‘int’)
   12 |  printf("%d\n", **pi);
      |   

EDIT2

fvv.c: In function ‘main’:
fvv.c:19:5: warning: passing argument 1 of ‘f2’ from incompatible pointer type [-Wincompatible-pointer-types]
   19 |  f2(&px);
      |     ^~~
      |     |
      |     int **
fvv.c:7:16: note: expected ‘void **’ but argument is of type ‘int **’
    7 | void f2(void** p)
Gennaro Arguzzi
  • 769
  • 1
  • 14
  • 27
  • Why are you converting to something as bizarre as `void**`? – tadman Jul 03 '20 at 16:41
  • Hello @tadman i'd like to learn how to do it because I need to understand some other library functions....and because I like to learn all the possibilities that a language offers. – Gennaro Arguzzi Jul 03 '20 at 16:43
  • Are you sure you want to "convert" between different levels of indirection? Converting between e.g. `void**` and `int **` would be slightly less worrying. – Yunnosch Jul 03 '20 at 16:44
  • Does this help, it is not actually a duplicate but seems very closely related: https://stackoverflow.com/questions/58280538/how-to-verify-if-a-void-pointer-void-is-one-of-two-data-types/58281061#58281061 – Yunnosch Jul 03 '20 at 16:45

1 Answers1

1

You can take any level of indirection you want, up to the blatantly, utterly absurd (void*******), but I'm not sure why this would be useful:

void f2(void** p)
{
    // Note you must maintain the same level of indirection
    int **pi = (int**)p;

    // Since this is a ** pointer, it requires ** to fully de-reference
    printf("%d\n", **pi);
}

To call this you need a pointer to a pointer:

int x = 1;
int *px = &x;
f2((void**) &px);

In C terms a pointer to a pointer is often interpreted to mean one of the two following things:

  • A two dimensional array
  • A mutable pointer argument

Neither of those apply here.

That being said, in C there's not a lot of rules as to what you can and can't convert. If you want to do it, C isn't going to get in your way, even if the resulting code makes no sense or will crash immediately when executed.

You can convert int* to void** and back again, C won't care, but you should have a really good reason for doing such a thing. Normally arbitrary pointers are almost always specified as void*, and as this can be recast into whatever you want, it's sufficient.

For example, you can specify void* as an argument when that pointer is actually int**, something you'll see quite often, as in thread_create taking a void* arg argument. That's not limited to mere pointers, you can cast to your heart's content.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • Thank you very much for your answer @tadman I edited my answer to report the output warning and error of the compiler. Could you help me to avoid warning and error please? – Gennaro Arguzzi Jul 03 '20 at 16:54
  • 1
    You can't assign to `int*` what's been cast to `int**`, the types must match. I made a typo in the original answer, but that was corrected a while back. – tadman Jul 03 '20 at 16:55
  • 1
    Easy fix, edited accordingly. It's worth noting it's great that you have all your compiler warnings turned on. That will help you identify problems a lot more quickly. – tadman Jul 03 '20 at 16:58