0

...then why is the code below give same value (meatballs) for address and the actual content? And how to make sense of %d value of meatballs, is it random?

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

int main()
{
    int i;
    int meatballs[5]= {1,2,3,4,5};

    printf("\nmeatsballs %p %p %d \t \n",meatballs, &meatballs, 
          meatballs);

    return 0;

}
jub0bs
  • 60,866
  • 25
  • 183
  • 186
  • 1
    [Is an array name a pointer in C?](http://stackoverflow.com/questions/1641957/is-an-array-name-a-pointer-in-c) – Lundin May 02 '16 at 06:37

2 Answers2

3
  1. meatballs is an array, and it has type int[5]. However C doesn't allow passing arrays by value, so array decays into pointer for function call. This is equivalent of pointer to first element of array &meatballs[0], and it has type int*.

  2. &meatballs is a pointer to an array, and it has type int(*)[5]. Since it's a pointer it can be passed to a function.

As you can see, both 1. and 2. return same address, but they have different types: pointer to integer array vs pointer to single integer.

Note: Types void* and int* don't necessarily have the same representation(1), and for %p only valid type is void*(2) or you will get undefined behaviour(3). Always convert pointer to void* when printing addresses:

printf("%p %p", (void*)meatballs, (void*)&meatballs);
  1. Last situation is same as first, but you are using wrong type specifier %d. Resulting type is again int* as in case 1, but it is interpreted as int. This is clear undefined behaviour, and output is garbage.

To print integer array element, use any of the following methods:

printf("%d %d %d", meatballs[i], *(meatballs + i), *meatballs);

First two will print array element at index i, and last will print first element. I recommend using the meatballs[i] in most cases, as it's most clear.


References to C standard (draft):

  1. N1570, 6.2.5 paragraph 28

    A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.48)... ...Pointers to other types need not have the same representation or alignment requirements.

  2. N1570, 7.21.6 paragraph 8

    p The argument shall be a pointer to void. ...

  3. N1570, 7.21.6 paragraph 9

    ... If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

user694733
  • 15,208
  • 2
  • 42
  • 68
  • Technically, there is no need to cast `meatballs` or `&meatballs` to `void*` as both are simply memory addresses which are `void *` to begin with. However, for the purpose of discussion it does no harm. – David C. Rankin May 02 '16 at 07:12
  • 1
    @DavidC.Rankin No, standard is pretty clear on this. `void*` is only required to have same representation as `char*` (N1570, 6.2.5 p28), and `%p` strictly requires `void*` (7.21.6 p8). – user694733 May 02 '16 at 07:19
  • Unless you are interpreting it differently, that means there is no cast required between the `char *` and `void *` pointers for any purpose to the extent `%p` cares. Are you saying something else that I'm missing? They are compatible types. Specifically, note:48 addresses `void *` and `char *` compatibility: 48) The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions – David C. Rankin May 02 '16 at 07:32
  • 1
    @DavidC.Rankin I was trying to say that `void*` and `int*` are not interchangeable, and that's why cast is needed on `printf`. But as you say, according to note 48, cast to `char*` should also suffice. – user694733 May 02 '16 at 07:46
  • Nicely structured and complete answer!-) Just for extending the last example: `printf("%d %d", *(meatballs + 1), meatballs[1]);` prints the array's second element (twice). And why not add the Standard reference mentioned in the comment to the answer? – alk May 02 '16 at 07:58
  • 1
    @alk Thank you. I added you suggestions. – user694733 May 02 '16 at 08:47
0

You have to use the unary dereference operator *, so that the actual value is shown as %d expects an integer.

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

int main()
{
    int i;
    int meatballs[5]= {1,2,3,4,5};

    printf("\nmeatsballs %p %p %d \t \n",meatballs, &meatballs, 
          *meatballs);

    return 0;

}

Look at the last parameter: *meatballs. This code actually prints 1 as value and is the first element in your array. So your guess is right and it is only a bug.

jub0bs
  • 60,866
  • 25
  • 183
  • 186
  • thanks for responding, now what about the meatballs and &meatballs having same value, are they allowed to be same if its a pointer. – Manish Kumar Singh May 01 '16 at 21:21
  • @ManishKumarSingh name of array evaluates the addr of the first element in the array, so meatballs and &meatballs has same value. The next element array will not. e.g. meatballs+1 and &meatballs+1 . –  May 01 '16 at 21:46