Why is the array name a pointer to the first element of the array?

This is always the case, I mean that the name of the array is always a pointer to the first element of the array. Why is this so? Is it something like implementing some kind of thing or language function?

+7
c arrays pointers
source share
3 answers

The name of the array is not the pointer itself, but in most contexts it splits into a pointer to the first element of the array. This is so because language defines it that way.

From C11 6.3.2.1 Lvalues, Arrays and Function Pointers , Clause 3:

_Alignof it is an operand of the sizeof operator, the _Alignof operator _Alignof or the unary operator & , or is a string literal used to initialize an array, an expression that is of type "array of type" is converted to an expression of type "pointer to type" that points to to the starting element of an array object and is not an lvalue value.

You can learn more about this topic (and a lot about subtle behavior) from the Arrays and Pointers section of the comp.lang.c FAQ .

From the Editor: The same behavior occurs in C ++, although the language indicates it a little differently. For reference, from the C ++ 11 project provided here, 4.2 Converting an array to a pointer , point 1:

An lvalue or rvalue value of type "array N T " or "array of unknown boundary T " can be converted to an rvalue of type "pointer to T ". The result is a pointer to the first element of the array.

+13
source share

The historical reason for this behavior can be found here .

C was derived from an earlier language named B (go figure). B was an unreasonable language, and memory was seen as a linear array of "cells", mostly unsigned integers.

In B, when you declared an array of N-elements, as in

 auto a[10]; 

N cells were allocated for the array, and another cell was reserved to store the address of the first element bound to the variable a . As in C, array indexing was done using pointer arithmetic:

 a[j] == *(a+j) 

This worked pretty well until Richie started adding structure types to C. The example he gives in the article is a hypothetical entry in the file system, which is the node identifier followed by the name:

 struct { int inumber; char name[14]; }; 

He wanted the contents of the structure type to match the data on the disk; 2 bytes for an integer followed by 14 bytes for the name. There was no good place to hide the pointer to the first element of the array.

So he got rid of him. Instead of allocating storage for the pointer, he designed the language so that the value of the pointer was calculated from the array expression itself.

This, by the way, is why array expression cannot be the purpose of an assignment; this is actually the same as 3 = 4; - You are trying to assign a value to another value.

+8
source share

Karl Norum answered the legal question on this question (and received my eminence on it), here is the answer to the implementation details:

To a computer, any object in memory is just a range of bytes and, with respect to memory processing, is uniquely identified by the address for the first byte and the size in bytes. Even if you have an int in memory, its address is not more or less than the address of its first byte. The size is almost always implicit: if you pass a pointer to an int , the compiler knows its size because it knows that the bytes at this address should be interpreted as int . The same goes for structures: their address is the address of their first byte, their size is implicit.

Now, language developers could implement similar semantics with arrays, as was the case with structures, but they weren’t for a good reason: copying was even more inefficient then than now, compared to just passing a pointer, structures were most often using pointers, and arrays are usually large. Prohibitively large to force semantics of meaning on them by language.

Thus, arrays were simply forced to be memory objects at all times, indicating that the name of the array would actually be equivalent to a pointer. In order not to violate the similarity of arrays with other memory objects, the size was again considered implicit (for the implementation of the language, and not for the programmer!): The compiler could just forget about the size of the array when it was accepted somewhere else and rely on the programmer to find out how many objects were inside the array.

This had the advantage that access to the array is overly simple; they break up into pointer arithmetic, multiplying the index by the size of the object in the array and adding this offset to the pointer. This is the reason why a[5] exactly matches 5[a] , it is short for *(a + 5) .

Another aspect related to performance is that to simplify the creation of a submatrix from an array, you just need to calculate only the starting address. There is nothing that would force us to copy data to a new array, we just have to remember to use the correct size ...

So yes, it has deep reasons, in terms of ease of implementation and performance, that array names decay into pointers the way they do, and we should be glad about that.

+2
source share

All Articles