Why can arrays be assigned directly?

Consider this piece of code:

void foo(int a[], int b[]){ static_assert(sizeof(a) == sizeof(int*)); static_assert(sizeof(b) == sizeof(int*)); b = a; printf("%d", b[1]); assert(a == b); // This also works! } int a[3] = {[1] = 2}, b[1]; foo(a, b); 

Output (no compilation error):

 2 

I can’t understand why b = a really. Even if arrays can decay to pointers, shouldn't they decay to constant pointers ( T * const )?

+5
source share
3 answers

Yes, it would be wise for the array parameters declared with [] to be adjusted using const pointers. However, const did not exist when this behavior was established.

When the C language was developed, it makes sense to pass an array by passing its address, or, more specifically, the address of the first element. You, of course, did not want to copy the entire array to pass it. Passing an address was an easy way to make the array known to the called function. (The semantics for reference types that we see in C ++ have not yet been invented.) To make it easier for programmers to write foo(ArrayA, ArrayB) instead of foo(&Array[0], &ArrayB[0]) , a mechanism for converting an array to a pointer to its first element was invented. (Per MM and C Language Development Dennis M. Ritchie, this parameter notation already existed in the predecessor language of Cs, B.)

This is great, you have hidden the transformation. But this is only where the function is called. In the called procedure, a programmer who thinks about passing an array is going to write void foo(int ArrayA[], int ArrayB[]) . But since we are actually passing pointers, not arrays, we need to change them to int *ArrayA and int *ArrayB . Thus, the idea was created that the parameters declared as arrays are automatically tuned to pointers.

As you noticed, this leaves the programmer with the ability to assign values ​​to parameters, which changes the visible base address of the array. It would be wise for the parameter declared as int ArrayA[] to be set to int * const ArrayA , so that the value of the ArrayA parameter could not be changed. Then it will look more like an array, whose address also cannot be changed, so this is better for pretending to skip arrays, even if we pass the addresses.

However, at that time, const did not exist, so it was impossible, and no one thought about inventing the const at that time (or at least worked on it enough to make him accept it).

There is a large amount of source code in the world that works with non-constant configuration. Changing the C language specification will now cause problems with existing code.

+4
source

They can not.

Arrays cannot be assigned. There are no arrays in foo . The syntax int a[] in the list of function parameters means to declare that a is of type "pointer to int ". The behavior is exactly the same as if the code was void foo(int *a, int *b) . (C11 6.7.6.3/7)

You can assign one pointer to another. As a result, both pointers point to the same location.


Even if arrays can decay to pointers, shouldn't they decay to constant pointers (T * const)?

A pointer retrieved from the decay array is an rvalue. The const qualifier only makes sense for lvalues ​​(C11 6.7.3 / 4). (The term β€œdecay” refers to the conversion of an argument, not the setting of a parameter).

+10
source

Citation C11 , chapter Β§6.7.6.3, function declarators (including prototypes)

Declaring a parameter as an `` array of type must be adjusted to a qualified pointer to the type, where type qualifiers (if any) are those that are specified in [ and ] the array type. [...]

So a and b are actually pointers, not arrays.

There is no destination for any type of array that happens here , so there is no problem with the code.

+8
source

Source: https://habr.com/ru/post/1273623/


All Articles