My embedded system got a C++11-capable version of g++, so I've been cleaning up code from
for( uint16_t* p = array; p < (&array)[1]; ++p ) {
*p = fill_value;
}
to
for( uint16_t& r : array ) {
r = fill_value;
}
which is much more readable.
Is there a range-based for loop which operates over all elements of array2[m][n]
?
The old version is
for( int16_t* p = array2[0]; p < (&array2)[1][0]; ++p ) {
*p = fill_value;
}
and I don't want nested loops, unless it's guaranteed the compiler will flatten them.
(FWIW, the compiler is the GNU 4.7.4 Linaro g++ ARM cross-compiler that ships with TI Code Composer Studio 6.0.0)
A multi-dimensional array is an array with more than one level or dimension. For example, a 2D array, or two-dimensional array, is an array of arrays, meaning it is a matrix of rows and columns (think of a table). A 3D array adds another dimension, turning it into an array of arrays of arrays.
A multidimensional array in MATLAB® is an array with more than two dimensions. In a matrix, the two dimensions are represented by rows and columns. Each element is defined by two subscripts, the row index and the column index.
Multi-dimensional arrays are an extended form of one-dimensional arrays and are frequently used to store data for mathematic computations, image processing, and record management.
Indexing multi-dimensional arrays Multi-dimensional arrays are indexed in GAUSS the same way that matrices are indexed, using square brackets [] . Scanning above, you can see that the value of the element at the intersection of the third row and second column of x1 is 8.
As an example, there are various ways to print and manipulate value of a multidimensional array.
int arr[2][3] = { { 2, 3, 4 }, { 5, 6, 7} };
First Method,
size_t count = 0 ;
for( auto &row : arr)
for(auto &col : row)
col = count ++;
Here in the first for loop we are referring to the two array. Then in the second array we have reference to the 3 elements of those subarrays separately. And we are also assigning count to col. So, it iterates over to the next element of the subarray.
Second Method,
for( auto &row : arr)
for( auto col : row)
cout << col << endl;
We take reference here in the first loop because we want to avoid array to pointer conversion.
If this is done( error case: first for loop is not a reference ),
for( auto row : arr) // program won't compile
for( auto col : row)
Here, we have int * in row. By the time we reach the second for loop. Because row is now int * and not a list the program will not compile. You have to create a list then only we can pass that it to ranged for loop and use it for iterating over that list.
vector<int> list = { *(row+0) , *(row+1) , *(row+ 2) } ;
Now we can use the list for iteration
for ( ----- : list)
for ( auto &a : array )
{
for ( int &x : a ) x = fill_value;
}
EDIT: You can try the following
const size_t n = 2;
const size_t m = 3;
int a[n][m] = { { 1, 2, 3 }, { 4, 5, 6 } };
for ( auto &x : reinterpret_cast<int ( & )[n * m]>( a ) ) x = 10;
for ( auto x : reinterpret_cast<int ( & )[n * m]>( a ) ) std::cout << x << ' ';
std::cout << std::endl;;
The output is
10 10 10 10 10 10
The advantage of this approach is that you can reinterpret any multidimensional array not only a two-dimensional array. For example
int a[n][m][k] = { /* some initializers */ };
for ( auto x : reinterpret_cast<int ( & )[sizeof( a ) / sizeof( ***a )]>( a ) )
{
std::cout << x << ' ';
}
std::cout << std::endl;;
Here's some code that will fill an arbitrary array (of statically known size):
#include <algorithm>
#include <iterator>
#include <type_traits>
template <typename T>
void fill_all(T & a, typename std::remove_all_extents<T>::type v);
template <typename T>
void fill_all_impl(T & a, typename std::remove_all_extents<T>::type v, std::false_type);
template <typename T>
void fill_all_impl(T & a, typename std::remove_all_extents<T>::type v, std::true_type)
{
for (auto & x : a)
fill_all(x, v);
}
template <typename T>
void fill_all_impl(T & a, typename std::remove_all_extents<T>::type v, std::false_type)
{
std::fill(std::begin(a), std::end(a), v);
}
template <typename T>
void fill_all(T & a, typename std::remove_all_extents<T>::type v)
{
fill_all_impl(a, v, std::is_array<typename std::remove_extent<T>::type>());
}
Example usage:
int a[3][4][2];
fill_all(a, 10);
Combining parts of Vlad's and Praetorian's answers, I decided to use:
template<typename T, size_t N, size_t M>
auto flatten(T (&a)[M][N]) -> T (&)[M*N] { return reinterpret_cast<T (&)[M*N]>(a); }
for( int16_t& r : flatten(array2) ) {
r = fill_value;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With