Is this possible at all? I'm trying to write a function which I'd like to include in a personal library for future use, and as it's afunction I'd liketo be able to just use as and when, it would be really useful to be able to check the length of an array provided to it.
The syntax
uint8_t MyFunction(uint8_t ArrayProvided[]){
lets one feed in an array easily enough, but I know that behind the scenes it is using pointers, and that means that if inside the function you try to call sizeof on the array, you always get "2" as the results, which is the size of the pointer.
I know one can supply an array size to a function as a separate variable, but if you're trying to make a function really resilient for future use (especially if it might be someday called from inside another function which an array has already been fed in to) then this isn't great. That variable showing the function length has to be provided from somewhere, and makes using the function in different projects more work.
So is there a way a function can check for itself the size of an array given to it?
Thanks
When you pass an array to a function what you are really passing is a pointer to the array. As a result the sizeof() function used within a function to determine the number of elements in the array will not work because it will return the size of the pointer rather than the number of bytes used by the array
One possible way round this is to put an end marker in the array in the last array position and use this to determine the size of the array. However, this requires that the end marker value does not appear within the data held in the array. This is how C style strings work by being terminated by a '\0' character that is used by functions that act on the string, such as strlen()
even if there are several function calls between where the array is defined and where its size is needed, why can't the size be passed down thru all the intermediate functions along with the array?
then there's the question of the size of the array or how many elements of the array are used? either value can be passed down
Thanks everyone, passing a size variable down through other functions ought to work, not as convenient, but ought to be workable. Unless you had something where the initial array to then be passed down was defined as having a size based on a variable supplied to it?
When many different array types and/or sizes are used, one might want to use the following trick to avoid large binaries due to multiple template instantiations.
Where would it get the size from? Dynamically allocated arrays do not store their size anywhere*.
The idea of passing arrays by pointers without any distinction was a mistake. The solution is to never let your arrays decay to a pointer in the first place.
In C++, you should pass arrays (both fixed-size and dynamic) to functions using a std::span.
(*) Usually, at least not for types with a trivial destructor.
Although std::span requires C++20, you can write your own basic version using only Arduino-compatible C++11. As an example, a very limited implementation could look like this: https://godbolt.org/z/K414vc9s5
Then you just replace any (pointer to) array arguments to your functions by the span class:
void func(my_span<int> array_view) {
println(array_view.size());
for (int element : array_view)
println(element);
}
int main() {
int array[] {1, 2, 3};
func(array);
}
There are more comprehensive alternatives, such as gsl::span (requires C++14 with standard library) or tcbrindle/span (requires C++11 with standard library).
When talking about function arguments, yes.
I'd argue that passing an array of unknown size to a function is almost always a mistake. If you don't know the size of an argument of array/pointer type, you cannot (safely) do anything useful with that array.
Usually, the size is either implicit, or passed as an extra parameter. Both options have shown to lead to countless bugs.
This still leaves room for disagreement between your constant and the actual size of the array you're working with:
constexpr int array_size = 3;
int foo[array_size];
int bar[2];
int your_function(int array[]) {
return array[array_size - 1];
}
your_function(bar); // bug
your_function(foo + 1); // bug
std::span supports arrays with compile-time constant sizes (in which case it only stores a pointer): std::span - cppreference.com