4

In some legacy code I have to maintain, & operators are put in front of arrays names whenever the arrays are to be passed as (void *) arguments

Here is a simple example :

char val = 42;
char tab[10];
memcpy(&tab, &val, 1);

It compiles with gcc or clang without errors or warnings. It also gives the expected result.

Is this syntax legal ?

Why does this works ?

Notes : I usually use one of the following syntax :

memcpy(tab, &val, 1);
memcpy(&tab[0], &val, 1);

Epilog :

As an additional test, I used a function taking a (char*) argument instead of (void*)

I get the following warning if I try to compile with clang :

warning: incompatible pointer types passing 'char (*)[10]' to parameter of type 'char *' [-Wincompatible-pointer-types]

Edit 1 : In the original example tab was given with a size of 1 element

I just changed the size to 10 for the sake of generality.

Edit 2 : As mentionned in the answers, memcpy takes (void*) and not (char*)

7
  • 2
    May as well throw in memcpy(a+0, &val, 1) just to cover third base too. (and I usually use your first example in your usual usage pattern). Commented Oct 19, 2013 at 18:48
  • 2
    Did you mean memcpy(&tab, &val, 1)? Commented Oct 19, 2013 at 18:49
  • The name of the array is already equivalent to a pointer to its first element. Using the & operator is not necessary, it isn't wrong either. Commented Oct 19, 2013 at 18:49
  • 1
    @HansPassant: tab and &tab are of different types. Both are valid only because memcpy() takes arguments of type void*. Commented Oct 19, 2013 at 18:58
  • 1
    @mbratch: Only because memcpy takes arguments of type void*; see my previous comment and my answer. Commented Oct 19, 2013 at 18:59

1 Answer 1

10

memcpy's parameters are of type void*, not char*. Any argument of pointer type (excluding function pointers) is implicitly converted to void*. This is a special-case rule that applies only to void*.

Given the declaration

char tab[1];

either tab or &tab is valid as an argument to memcpy. They evaluate to pointers of different types (char* and char (*)[1]), but both pointing to the same memory location; converting either to void* yields the same value.

For a function that actually requires a char* argument, only tab is valid; &tab is of the wrong type. (For a variadic function like printf or scanf, the compiler may not be able to detect the type mismatch.)

Sign up to request clarification or add additional context in comments.

3 Comments

A big +1 (and I wish I could up-vote it twice) for pointing out the differences between the resulting pointer types and their valid usage scenarios.
I think it perfectly answers my question. Thanks !
@haccks: Or both. (Neither is required.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.