7

I have the following class in C++11:

class MyTable
{
    public:
    enum class EntryType
    {
        USED, FREE
    };

    MyTable(EntryType value)
    {
        for (uint32_t i = 0; i < 10; ++i)
        {
            memset(_table[i].data(), (int)value, sizeof(_table[0][0]) * 50);
        }
    }
    array<array<EntryType, 50>, 10> _table;
}

Trying to construct an object of MyTable with value of EntryType::FREE, every item in the 2-dimensional array has the value of 0x01010101 (1b every 8 bits), instead of the expected value of just 0x1

I'm guessing it has something to do with my value being casted to int, but I don't know what I'm supposed to do in order to fix it.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
itzhaki
  • 317
  • 2
  • 10

2 Answers2

6

memset() is expected to work that way, since it's

sets each byte of the destination buffer to the specified value.

Read more in Why is memset() incorrectly initializing int?

However, be careful, since as juanchopanza said, std::array may have padding at the end (read more in std::array alignment ), which means that this approach might fail.


Since it's a 2D array, you could use a range-based-for loop and std::array::fill, like this:

for(auto& row : _table)
    row.fill(value);

as renzo stated.

In case you do not want to set every row at the same value, you could do it like this of course:

for(auto &row : array)
    for(auto &col : row)
         col = value; 

Read more in range-based for on multi-dimensional array.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • 1
    range-based-for could also be used. – The Techel May 26 '17 at 09:14
  • Or another variant: `for(auto& array : _table) array.fill(value);` – renzo May 26 '17 at 09:20
  • 1
    `std::array` can have padding at the end, so `memset` isn't guaranteed to work when used as in OP's code. – juanchopanza May 26 '17 at 09:22
  • @juanchopanza ah thank you, didn't know that! Thank you The Techel and renzo for the suggestions, they really improved the answer! =) – gsamaras May 26 '17 at 09:27
  • 1
    That solved my problem, thank you for the detailed reply. The `int` in `memset` threw me off, as I was not aware it is casted to `unsigned char` – itzhaki May 26 '17 at 10:05
  • @juanchopanza (notwithstanding how the implementation putting padding there seems stupid to me) Why would padding at the end make any difference to this? The `memset` would be performed from the beginning until the last element, inclusive. The padding at the end, after the last element, should not be touched nor read, so it shouldn't be relevant at all. – underscore_d May 26 '17 at 21:56
3

This can be done with a ranged-based for loop and the std::array::fill member function.

MyTable(EntryType value)
{
    for (auto& row : _table) {
        row.fill(value);
    }
}

This will continue to work even if you change the array dimensions.

Blastfurnace
  • 18,411
  • 56
  • 55
  • 70