3

I read this in my book (and many sources on the internet):

The array variable points to the first element in the array.

If this true, then the array variable and the first element are different. Right?

It means by below code, it will produce two different results:

int main(){
    char msg[] = "stack over flow";
    printf("the store string is store at :%p\n",&msg);
    printf("First element: %p\n",&msg[0]);
}

But I receive the same results for the two cases. So, by this example, I think we should say: the array variable is the first element. (because it has the same address)

I don't know if this true or wrong. Please teach me.

pb2q
  • 58,613
  • 19
  • 146
  • 147
hqt
  • 29,632
  • 51
  • 171
  • 250

7 Answers7

8

The array variable signifies the entire memory block the array occupies, not only the array's first element. So array is not the same as array[0] (cf. sizeof array / sizeof array[0]). But the array's first element is located at the same memory address as the array itself.

Saying the array points to the first element is also incorrect, in most circumstances, an array expression decays into a pointer to its first element, but they are different things (again cf. sizeof for example).

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • Can you tell me more about this point : it located at the same memory address but it's different. I don't get in at this point, because I think, if it located same address, it should be same. Thanks :) – hqt Aug 09 '12 at 14:02
  • @hqt the addresses **are** the same, but the point is that `msg` and `msg[0]` will _behave_ differently. They're two different types. Look at the notes about pointer arithmetic, e.g. `(&msg + 1)` and try it yourself. – pb2q Aug 09 '12 at 14:05
  • 2
    @hqt The sizes are different. The array `msg` occupies 16 bytes, its first element occupies only the first of these bytes. It's like the address of the first member of a struct is the same as the address of the struct, but they are different things. If you have an entity A of x bytes located at some address, and an entity B of y bytes at the same address, A and B are distinct entities if `x != y`. (They can be different entities even if `x == y`.) – Daniel Fischer Aug 09 '12 at 14:06
  • 3
    It's like saying your hand and your thumb start at the same point in space. One is an array of fingers that's all – Eregrith Aug 09 '12 at 14:06
  • @Eregrith That's a nice picture (even if a hand is more than just an array of fingers). – Daniel Fischer Aug 09 '12 at 14:07
  • @Eregrith ha ha, so funny. although I need some time to understand clearer, but your example makes me feel a lot :) – hqt Aug 09 '12 at 15:11
5

They point to the same address, i.e. printf will show the same value but they have different types.

  • The type of &msg is char(*)[16], pointer to array 16 of char
  • The type of &msg[0] is char *, pointer to char

A cheap way to test this is to do some pointer arithmetic. Try printing &msg + 1.

This C FAQ might prove useful.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
5

The array variable is the whole array. It decays into a pointer to the first element of the array.

If you look at the types:

  • msg is of type char [16]
  • &msg is of type char (*)[16]
  • &msg[0] is of type char *

So in a context where msg can decay into an array, for example when passed as an argument, its value would be equal to &msg[0].

Let me draw this:

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
|s|t|a|c|k| |o|v|e|r| |f|l|o|w|\0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+

Imagine the starting point of this array, where 's' is located is address 0x12345678.

  • msg itself, refers to the whole 16 bytes of memory. Like when you say int a;, a refers to 4 bytes of memory.
  • msg[0] is the first byte of that 16 bytes.
  • &msg is the address where array begins: 0x12345678
  • &msg[0] is the address of first element of array: 0x12345678

This is why the values of &msg and &msg[0] are the same, but their types are different.

Now the thing is, msg by itself is not a first class citizen. You cannot for example assign arrays. That is why, in most of the cases, the array will decay into its pointer.

If you know function pointers, this is very similar:

int array[10];
int function(int);
  • In int *var = array, array decays to a pointer (&array)
  • In void *var = function, function decays to a pointer (&function)

Note that, in case of function pointers, we like to keep the type, so we write:

int (*var)(int) = function;

Similarly, you can do with arrays:

int (*var)[10] = array;
Shahbaz
  • 46,337
  • 19
  • 116
  • 182
2
char myChar = 'A'
char msg[] = 'ABCDEFGH'

When you type myChar you get value. But with msg you get pointer to first char(for values you have to use msg[x])

msg = &msg[0]

This can help you to understand, I think.

Meloun
  • 13,601
  • 17
  • 64
  • 93
1

Look at it this way:

&msg = 0x0012
&msg[0] = 0x0012
&msg[1] = 0x0013

In this case &msg[1] is pointing to msg+1. When you reference &msg or &msg[0] you are referring to the same address of memory because this is where the pointer starts. Incrementing the array variable will increment the pointer by +1 since a char variable is only 1 byte in size.

If you do the same trick with say an integer you will increment the pointer by +4 bytes since an integer is 4 bytes in size.

Blackninja543
  • 3,639
  • 5
  • 23
  • 32
1

When you use an array expression, the compiler converts it to a pointer to the first element. This is an explicit conversion specified by the 1999 C standard, in 6.3.2.1 3. It is a convenience for you, so that you do not have to write &array[0] to get a pointer to the first element.

The conversion happens in all expressions except when an array expression is the operand of sizeof or the unary & or is a string literal used to initialize an array.

You can see that an array and its first element are different by printing sizeof array and sizeof array[0].

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
1

In most circumstances, an expression of array type ("N-element array of T") will be replaced with / converted to / "decay" to an expression of pointer type ("pointer to T"), and the value of the expression will be the address of the first element in the array.

So, assuming the declaration

int a[10];

the type of the expression a is "10-element array of int", or int [10]. However, in most contexts, the type of the expression will be converted to "pointer to int", or int *, and the value of the expression will be equivalent to &a[0].

The exceptions to this rule are when the array expression is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration.

So, based on our declaration above, all of the following are true:

  Expression   Type         Decays to     Value
  ----------   ----         ---------     -----
           a   int [10]     int *         address of the first element of a
          &a   int (*)[10]  n/a           address of the array, which is the
                                            same as the address of the first
                                            element
       &a[0]   int *        n/a           address of the first element of a
          *a   int          n/a           value of a[0]
    sizeof a   size_t       n/a           number of bytes in the array 
                                            (10 * sizeof (int))
   sizeof &a   size_t       n/a           number of bytes in a pointer to 
                                           an array of int
   sizeof *a   size_t       n/a           number of bytes in an int
sizeof &a[0]   size_t       n/a           number of bytes in a pointer to int

Note that the expressions a, &a, and &a[0] all have the same value (address of the first element of a), but the types are different. Types matter. Assume the following:

int a[10];
int *p = a;
int (*pa)[10] = &a;

Both p and pa point to the first element of a, which we'll assume is at address 0x8000. After executing the lines

p++;
pa++;

however, p points to the next integer (0x8004, assuming 4-byte ints), while pa points to the next 10-element array of integers; that is, the first integer after the last element of a (0x8028).

John Bode
  • 119,563
  • 19
  • 122
  • 198