1

The following program prints that a and array share the same address. How should I understand this behavior? Is it &arr the address for the pointer arr, which contains the beginning address the 10 chars?

#include <stdio.h>

int main()
{
    char arr[10] = {0};

    char* a = (char*)(&arr);

    *a = 1;

    printf("a=%p,arr=%p.\n", a, arr);
    printf("%d\n", arr[0]);
    return 0;
}
Alex
  • 1,737
  • 2
  • 20
  • 35
  • `&arr` is the address of the first element of `arr`. Of course, `a` has the same value, because you assigned it that value in the first place. – Frédéric Hamidi Sep 02 '14 at 14:59
  • @Alex: The first thing you have to learn is that there's no such thing as "pointer `arr`". `arr` array is array, not a pointer. There's no pointer of any kind there. There's massive amount of information properly explaining what an array is on the Net. – AnT stands with Russia Sep 02 '14 at 15:32

4 Answers4

2

When you allocate an array in C, what you get is something like the following:

          +---+ 
  arr[0]: |   |
          +---+
  arr[1]: |   |
          +---+
           ...
          +---+
arr[N-1]: |   |
          +---+

That's it. There's no separate memory location set aside for an object named arr to store the address of the first element of the array. Thus, the address of the first element of the array (&arr[0]) is the same value as the address of the array itself (&arr).

Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T" and the value of the expression will be the address of the first element of the array.

So the type of the expression arr in the first printf call is char [10]; by the rule above, the expression "decays" to type char *, and the value is the address of arr[0].

In the expression &arr, arr is the operand of the unary & operator, so the conversion isn't applied; instead of getting an expression of type char **, you get an expression of type char (*)[10] (pointer to 10-element array of char). Again, since the address of the first element of the array is the same as the address of whole array, the expressions arr and &arr have the same value.

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

In idiomatic C, you should write char *a = arr; or char *a = &(arr[0]);. &arr is normally a char **. Even if modern (C++) compilers fixe it automatically, it is not correct C.

As arr is an array of char, arr[0] is a char and arr is the same as &(arr[0]) so it is a char *. It may be strange if you are used to other languages, but it is how C works. And it would be the same if arr was an array of any other type including struct.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • `&arr` will be `char (*)[10]`, that is a pointer to an array of 10 `char`. @FrédéricHamidi – alk Sep 02 '14 at 16:21
  • 1
    @FrédéricHamidi You may believe what you want, but what really counts is what the compiler will believe :-), I've editet my post to be more clear. – Serge Ballesta Sep 02 '14 at 17:11
0

The address printed out by arr and a is the memory address of the first element of the array arr. (Remember, the name of an array is always a pointer to the first element of that array.) This is because after you have defined the array arr, you define a as a pointer to the same address in memory.

mr_T
  • 2,571
  • 3
  • 22
  • 39
0

According to the C Standard (6.3.2.1 Lvalues, arrays, and function designators)

3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

The address of an array is the address of its first element. So though these types are different

char ( * )[10] ( that corresponds to &arr ) and char *(that is used in the casting in statement char* a = (char*)(&arr); ) they will have the same value that is the address of the first element of the array.

If you would not use the casting then the correct definition of the pointer initialized by expression &arr would be

char ( *a )[10] = &arr;

The difference is seen then the pointer is incremented. For your definition of pointer a the value of expression ++a will be greater sizeof( char) than the initial value . For the pointer I showed the value of expression ++a will be greater 10 * sizeof( char ) than the initial value.

In your case the type of expression *a is char and you may write *a = 1; while in my case the type of expression *a will be char[10] and you may not write *a = 1;

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335