Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How C++ compiler knows the length of an array [duplicate]

Tags:

c++

c++11

For example, in the main function, I can write int arr[42], and I can use range for loop without indicating its length for (auto i : arr). It works well. Compiler will know its length.

If I pass this array to another function, such as void foo(int arr[]), I cannot use range for loop because the compiler doesn't know its length.

After all, if I have this template template<class T, size_t N> void arr_init(T (&foo)[N]), I can call it by arr_init(x). Obviously, the compiler calls arr_init(int (&)[42]).

I guess the compiler knows the length of array through its declaration int[42]. Am I right? I've got this question when I use range for loop and learn templates. I haven't met such problem before, when I was using C.

like image 383
yuanqili Avatar asked Jan 18 '26 22:01

yuanqili


1 Answers

The array type T[N] is distinct from the array type T[M] for a type T and two distinct sizes N and M. So, the length of an array is built into the type.

OTOH, arrays are automatically decayed to pointers in a function calls argument list. In other words, there is no distinction between these three function signatures:

int func(int []);
int func(int[5]);
int func(int[10]);
int func(int*);

All the above signatures are simply taking an int*. If you want to preserve the array type, you need to create a function which takes an array reference as an argument. That is exactly what you achieve in your example template<class T, size_t N> void arr_init(T (&foo)[N]). Inside arr_init, foo behaves like an array because it is a reference to an array type.

For an array arr of type T[N], the range-based for uses the expressions arr and arr+N as the start and end points, respectively.

For class types, member functions begin and end, if present, are used to determine the endpoints, failing which the non-member overloads, begin and end are used.

(begin and end, as opposed to std::begin and std::end, since the generic usage of begin and end in the standard library is like this:

using std::begin;
begin(...);
using std::end;
end(...);

This allows ADL to find user-defined begin and end overloads.)

like image 122
Pradhan Avatar answered Jan 20 '26 12:01

Pradhan