Is it ok to treat multidimensional std::array as continuous block of data?

Viewed 82

Can multi-dimensional std::array be treated as a continuous block of data? That is, is this legal:

#include <array>
#include <iostream>
#include <cstring>

// just to show what's happening, otherwise unrelated
template<typename T>
void print_array(const T &data)
{
    for(const auto &row : data) {
        for(const auto &item: row) {
           std::cout << static_cast<char>('a' + item);
        }
        std::cout << '\n';
    }
    std::cout.flush();
}

// function to fill a block of bytes
void filler(uint8_t *data, size_t size) {
    while(size != 0) {
        *(data++) = size % 27; // just a changing number
        --size;
    }
}

// test code
int main()
{
    std::array<std::array<uint8_t, 30>, 20> data;
    std::memset(&data, 0, sizeof(data)); // use &data, is this legal?
    print_array(data); // seems to print all 'a' ok...
    std::cout << std::endl;
    filler(data.begin()->begin(), 30*20); // use pointer to first item, legal?
    print_array(data); // seems to print alphabet pattern ok...
}

Print-out is what one might expect, first a character rectangle of letter a, then a rectangle filled with characters a-z.

The same subject is discussed at least here and here, but I think multi-dimensional arrays may be a different case.


Additionally, even if static_assert(sizeof(data) == sizeof(uint8_t)*20*30) holds, so the data is continous in memory with no gaps, does even this guarantee anything? Or is using the same pointer to access different arrays through indexing illegal anyway?

1 Answers

You may want to take a look into this question and its accepted answer. Basically, implementations will have a plain array T[N] as the first member of the std::array but nothing stops them putting members after that, in which case sizeof(data) != 30 * 20.
This might seem a bit farfetched, but there were reports of this happening: link. So if you want your code to be "legal", you will have to treat each inner array independently and iterate over them instead, possibly jumping some space at the end of each. If this is something you really need to do, which I highly doubt, you could do a static_assert to see if the size of std::array is what it should be.

Related