Why is the size of the array passed to the function via a link known to the C ++ compiler?

I know that when I want to pass an array to a function, it will decay to a pointer, so its size will not be known, and these two declarations are equivalent:

void funtion(int *tab, int size); 

and

 void funtion(int tab[], int size); 

And I understand why. However, I checked this when passing the array as a reference:

 void funtion(int (&tab)[4]); 

the compiler will know the size of the array and will not let me pass an array of different sizes as an argument to this function.

Why? I know that when I pass an array to an address, the size is not taken into account when calculating the position of the ith element in the array, so it is discarded even if I explicitly include it in the function declaration:

 void funtion(int tab[4], int size); 

But what is the difference when I pass an array by reference? Why is its size known to the compiler?

Note. I am interested in arrays whose size is known at compile time, so I did not use any templates.

I found a similar question about stack overflow, but it does not answer my question - it does not explain why the compiler knows the size of the array, there is only some information on how to pass arrays to functions.

+5
source share
3 answers

Because it is possible, and because verification adds extra security. The compiler knows the size of the array, because you say that, right there in the function declaration. And since this information is available, why not use it to signal errors in your source code?

The real question is why your last example would not perform the same test. Unfortunately, this is another piece of C legacy - you never pass an array, it always breaks into a pointer. The size of the array becomes irrelevant.

Can a check be added? Maybe, but that would be limited use (since we all use std :: array now - right !?), and because it will undoubtedly break some code. This is for example:

 void func (char Values [4]); func ("x"); 

This is currently legal, but there will be no additional verification of the size of the array.

+6
source

Because there is no odd implicit type change committed by the compiler in this case. Usually when you write:

 void func(int[4]); 

or

 void func(void()); 

The compiler decides to โ€œhelpโ€ you and translates them into:

 void func(int *); 

or

 void func(void(*)()); 

The funny thing though is that it wonโ€™t help you this way when you try to get one of them back. Try to write:

 int func()[4], func1()(); 

Ooops - surprise - compiler error.

Otherwise, arrays are arrays and have a constant size, which can be obtained using the sizeof operator.

However, this is often forgotten due to the compiler behavior described above, as well as due to the implicit pointer conversion applied to objects of the array type when this is not expected. And this is very common. Although there are a few exceptions when the implicit conversion of array objects is not applied:

 size_t arr[4], (*parr)[3] = &arr, //taking the address of array (&refarr)[3] = arr, //storing reference to array sizearrobject = sizeof(arr); //taking the array object size 

The above examples will cause a compiler error due to incompatible types in the second and third lines.

I am talking about cases where the arr object does not automatically convert to something like this:

 (size_t*)&arr 
0
source

Well, there are several ways to pass an array to work. You can pass it with a pointer by reference, and there are ways to determine whether or not to determine its size explicitly for both methods.


In your question, you are comparing these two ways:
  • Pointer to the first element: void f(int *arr)
  • Link to the entire array: void f(int (&arr)[size])

You ask why you need to specify the size in only one of these cases.

It sounds like you think the only difference between the two is that one uses a pointer and the other uses a link. But this statement is wrong, they have more differences: one is a pointer to the first element, and the second is a link to the entire array.


You can pass an array with a pointer to the entire array:
 void f(int (*arr)[size]) 

Compare this with your example with passing refence to the whole array:

 void f(int (&arr)[size]) 

They are similar, they have similar syntax, they both explicitly determine the size of the array.


Also consider the following:
 void f(int &arr) 

It is like passing a single int by reference, but you can pass an array of unknown size to it.

Alternative pointer to it

 void f(int *arr) 

You ask why you need to specify the size of the array in only one of these cases. This is because of the syntax you used, not because it is a pointer and the other is a link.

As I said, you can use a pointer or a link. And you can specify the size of the array, or you can allow the use of an array of any size. These two are not connected.

 // by pointer by reference /* Any size */ void f(int *arr) void f(int &arr) /* Specific size */ void f(int (*arr)[x]) void f(int (&arr)[x]) 
0
source

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


All Articles