Everyone knows that the name of the array is the address of the first element in the array, but it would have been so easy if not taking the address from the name of the array.

There is such an array declaration: char array[] = "String";

If we write: array or &array[0] - we get the address of the first element in the array, the first option is implicit, the second is explicit.

I thought, hmm, but what if I write &array - at first glance, nothing strange is the same address as array or &array[0] , but if you dug deeper, i.e., &array+1 , we will see that the address will increase in length lines (for me it is strange, I have never seen it, except in the parameters, when the argument was a pointer to an array of elements of a certain number, just like now)

I wonder if there is an alternative to this behavior ( &array )? So far I have thought of this way: (char (*)[sizeof(array)])array - but is this correct?

In addition, the following behavior is interesting: If we write *array we get an array element exactly like array[0] , but if we write *(&array) - we don't get an array element, we get the same address that points to the first element , but with the only difference that its address arithmetic fell from a whole array to one character.

Is it possible to say that in this case it is a pointer change to the level of a pointer to a character (such a kind of pointer downgrade)?

And what happens to an array when we write *(&array) in your opinion?

    2 answers 2

    If you have a view pointer

     T *p; 

    then 1) for pointer arithmetic, the sizeof( T ) value is used, and 2) pointer dereferencing yields the lvalue pointed to by the pointer.

    For example, if you have the following code snippet

     int a[] = { 1, 2 }; int *p = &a[0]; 

    then the value of the pointer after the expression ++p will be equal to

     значение указателя перед инкрементом плюс значение sizeof( int ) 

    In this case, as a result, the pointer will point to the element a[1] .

    If there is a declaration of the next array

     char array[] = "String"; 

    then it is equivalent to the following array declaration

     char array[7] = "String"; 

    If you enter typedef announcement

     typedef char T[7]; 

    then the declaration of the above array can also be written as

     T array = "String"; 

    Therefore, to declare a pointer to this object, you should write

     T *p = &array; 

    And, as shown above, for pointer arithmetic for pointer p , the expression sizeof( T ) , which is equal to sizeof( char[7] ) .

    By dereferencing this pointer, you get a lvalue object of type char[7]

    This is easy to check by completing a sentence.

     printf( "%zu\n", sizeof( *p ) ); 

    the result of which will be a value of 7 , that is, the length of an array of type char[7] is obtained.

    However, when there is an array as an object obtained after dereferencing a pointer, it is converted to expressions with a few exceptions to a pointer to its first element.

    From standard C (6.3.2.1 Lvalues, arrays, and function designators)

    3 If you want to use it, it can use it. this is not a lvalue. The behavior is undefined.

    Therefore, for the above example, if the expression *p is not used as an operand of the sizeof operator or the & operator, then the resulting array is implicitly converted into a pointer to its first element. Therefore, for example, the expression **p gives an object of type char with the value 'S' .

    • typedef char string[]; string a = "Hello World\n"; string *ptra = &a; printf("%p - %p\n", &a, &a+1); printf("%p - %p\n", ptra, ptra+1); - MaximPro
    • why in the last printf I get error: invalid use of array with unspecified bounds , although in the previous printf the same thing - MaximPro
    • @MaximPro What does "array exit error" mean? ptra is a pointer to an incomplete type. Therefore, pointer arithmetic is not applicable. - Vlad from Moscow
    • @MaximPro The char [] type is not a full type, that is, the size of this array is unknown. Therefore, a pointer to this type is a pointer to an incomplete type. It is impossible to calculate the address of the next object without knowing the size of the current object. - Vlad from Moscow
    • Aha thanks, I thought that the size was automatically determined after the array was initialized with the string - MaximPro
     char array[] = "String"; 

    The type of array is char[7] - an array of 7 characters.
    Accordingly, &array is a pointer to an array of 7 characters.
    Therefore, &array+1 is a pointer to the next array of 7 characters. Well, *(&array) is an array of seven char (roughly speaking, the same as array ).

    "I think so." (c) Pooh