If I try to display the length of an array in C++ , using the function sizeof
, it correctly displays the result, which in this case is 8.
int main()
{
int array_enteros[]={'9','8','7','6','5','4','3','2'};
int longitud=sizeof(array_enteros)/sizeof(*array_enteros);
cout<<longitud<<endl;
return 0;
}
What I don't like is that you have to enter the word array_enteros
twice to know the length, and for this, it would be better to get it through a function.
int obtener_longitud_array(int* array_enteros)
{
return sizeof(array_enteros)/sizeof(*array_enteros);
}
int main()
{
int array_caracteres_enteros[]={'9','8','7','6','5','4','3','2'};
int longitud=obtener_longitud_array(array_caracteres_enteros);
cout<<longitud<<endl;
return 0;
}
In this case, it returns 1, which is a different value.
Will there be any problem in the parameters of the function?
Problem.
The problem with your function
obtener_longitud_array
is that you lose the size information when passing the parameterarray_enteros
(plus you can only calculate the size of integer arrays).Explanation.
C++ is a strongly statically typed language , this means you can't change types at
object
runtime and everything has a concrete type (no wildcard types like .net ) .But sometimes C++ gives the feeling of being dynamically typed because there are implicit type transformations. One of these implicit transformations is the array-to-pointer transformation, according to the C++ standard (translation and emphasis mine):
Arrangement of
N
T
would be:Where
T
would be any type and anyN
value.Unknown extension fix
T
would be:where
T
would be any type, and is the array type you are using in your example.When passing the array
array_enteros
to the functionobtener_longitud_array
, the array goes through the above conversion ( §4.2 ) and loses its original type. The original type of the array contains the size.Size as part of type.
An array of
N
T
or an array of unknown extensionT
contains the size as part of its type:This is why the size can be detected using function overloads:
So your function
obtener_longitud_array
could be a template that gets the size of the array like so:Or you could generalize it for non-integer types like Dolmens has done . But instead of re-inventing the wheel I would use the standard library
std::extent
header utility:<type_traits>
The problem is that the function does not receive an array, but a pointer, which has size 1, pointers work like arrays but they are not the same.
You can use a macro to solve this problem
and then use GetSize as if it were a function
Since you're in C++, you can use the C++ way of doing things : using
template
.1. C++11,
constexpr
:It compiles without problems with
2. C++98, without
constexpr
:The only thing that changes is precisely the removal of that keyword.
It compiles without problems with
Test code:
Valid for C++98 and above:
The output is:
As you can see, it distinguishes between fixes and non-fixes . In the first case, it returns the number of elements (whether specified when declaring the variable or omitted). In the second, it returns
0
.Why 2 versions?
The first is
template
not strictly necessary. It is to avoid errors if you use it on variables that are not arrays . It makes use of the SFINAE feature of the language: when trying to instantiate a template and the parameters don't match , it does n't raise an error, but keeps looking for other versions of thetemplate
one that do match.In our test code, if we omit the first version of the template
My g++ spits out the following:
However, with both versions, the compiler tries both , and, depending on the case, it will succeed with one or the other. These attempts are what allow us to discriminate between normal variables and arrays .
Another way to do it, using C++11 and the
template std::remove_all_extents< T >
:Which, in a very free translation on my part, comes to say:
T
it is of the formtipo[]...
(with any number of dimensions, obtenemos el tipo base
T`.T
it is not of the formtipo[]...
, we still get the typeT
.This can be used to get the size of any variable, whether or not it is an array : if it is, we can get the size of its base type; if it is not, we still get the size of the base type. Therefore, in any case, it is enough for us to divide the size of the variable by that
typedef type
obtained from thetemplate
:Shows the following: