Home > Blockchain >  Pass array to a function as a pointer and value
Pass array to a function as a pointer and value

Time:12-23

What is the deference between passing array this way:

static char arr[N];

void func(void *buf, size_t size) {
    // ...
}

int main(void) {
    func(arr, N);

    // ...
}

And this way:

// ...

int main(void) {
    func(&arr, N);

    // ...
}

Is there any deference in those listings? It seems that the 2nd version passes an array as void **, but is it really so?

CodePudding user response:

The first is correct and the second is wrong or at least very questionable.

arr when used in an expression or passed to a function, gets adjusted to a pointer to the first element. So it turns equivalent to char*.

In the second example, &arr is one of the few exceptions to this "array decay" rule. Instead of a pointer to the first element, we get a pointer to the whole array, type char(*)[N]. This type is not compatible with char*, so if you would attempt to cast the void* buf to a char* inside the function, the second example causes a subtle bug.

The reason why the second example compiles at all is because void* (and only that type, not void**) is a special pointer type that can be converted to/from any other pointer to object. Should you change the function to

void func(char *buf, size_t size)

Then func(&arr, N); gives the expected compiler diagnostic "passing argument 1 of 'func' from incompatible pointer type".

Now as it happens, if you write the function like this

void func(void *buf, size_t size) {
    char* ptr = buf;
    for(int i=0; i<size; i  )
    {
      printf("%c ", ch[i]);
    }
}

It will most likely work for either version, because the address of the first item (char*) is the same as the address of the array (char(*)[N]). Also, C's peculiar type system allows us to access a memory location of some type through an array or struct of items of that same type ("the strict aliasing rule").

Best practices:

  • Use the first version.
  • Avoid the use of void* when possible, since they are type unsafe.
  • Be as explicit with types as you can and don't rely on implicit type conversions.
  • Related