Search code examples
cprotocol-buffersc99c89

What is the purpose of void *array = *(void **) member + siz * (*p_n);


I am trying to get a protobuf-c example compiled with a C90 compiler (MS VS2012).

Within the protobuf-c source code there are two C99 specific things that can easily be changed to be compatible with C90, i.e. variable declaration in the middle of a scope (not allowed in C90) and instantiation of structs via the .-syntax (e.g. some_struct_type name = {.a=1,.b=2}).

I am now stuck with one compile error left. The respective line in source file 'protobuf-c.c' reads:

void *array = *(void **) member + siz * (*p_n);

Where member is define as void * and p_n as size_t *. And the respective error is

error C2036: 'void *' : unknown size

Please note this is valid for protobuf-c version 1.0.1 (see the respective source code, at line 2404). This line has been changed in version 1.0.2 to

void *array = *(char **) member + siz * (*p_n);

with this comment. Changing the line accordingly eliminates the compilation error.

My questions are:

  • I would like to understand this line of code.
  • Can I switch to the *(char **) version?
  • What is the error message telling me?

(For some other reason I want to stick to protobuf-c 1.0.1)


Solution

  • parameter passed as member is an address of a pointer to char pointer . First the cast and defererence get that pointer.( The address of the pointer is passed so that the pointer can be changed in the function. )

    The addition siz * (*p_n) increments the pointer to the correct element.

    The whole line could be rewritten as:

    char** pm = member ;
    char* m = *pm ;
    void *array = m + siz * (*p_n);
    

    A change from void* to char* is made so that pointer arithmetic is possible, as C Standard doesn't allow it on void pointers. The error message is telling you that, size of the object void* is pointing to is not known, there for you have to use a char* pointer.

    As long as the object passed to the function has the type char** you can switch to char** version.