Как memset () работает в C ++ - PullRequest
0 голосов
/ 03 сентября 2018

Я создал логический 2D-массив и использовал memset так:

bool chk[3][3];

memset(chk, 1, 9*sizeof(chk[0]));

Я получил вывод, как и ожидалось, используя следующие блоки кода (по 1 в каждой строке)

for(int i = 0 ; i < 3; i++){
    for(int j = 0; j < 3; j++)
        cout<<chk[i][j] <<" ";
    cout<<endl;
}

но когда я попытался манипулировать массивом, я получил неожиданный результат

а потом я попробовал с

memset(chk, 1, 9*sizeof(chk[0][0]));

и на этот раз все было хорошо и получил ожидаемый результат (после манипуляций)

Не могли бы вы помочь мне указать, что именно произошло в memset ()?

Ответы [ 4 ]

0 голосов
/ 03 сентября 2018

sizeof(array) очевидно, вернул бы размер массива в байтах. В первом случае массив, переданный оператору, является одним из подмассивов. Многомерные массивы в C ++ - нет. Это одномерные массивы массивов. Выполните sizeof(chk), чтобы оценить размер полного массива и разделите его на sizeof(chk[0][0]), чтобы получить количество элементов. Не используйте memset, потому что если что-то не так с двоичным представлением bool, используйте std::fill.

0 голосов
/ 03 сентября 2018

Давайте посмотрим, что написано в документации std::memset:

Если число больше размера объекта, на который указывает dest, поведение не определено.

В первом коде 9*sizeof(chk[0]) больше, чем размер chk, и, следовательно, поведение программы не определено.

memset(chk, 1, sizeof chk) было бы проще и, очевидно, правильно в отношении размера.

0 голосов
/ 03 сентября 2018

У вызова memset в вашем первом фрагменте кода есть три проблемы:

  1. Неверный расчет размера. Вместо 9*sizeof(chk[0]) вы можете использовать 3*sizeof(chk[0]). Но на самом деле вы должны просто использовать sizeof(chk), потому что у вас есть локальная переменная, а не указатель, как это было бы с формальным аргументом.

  2. Предположение, что представление памяти true является битовым шаблоном 1, не гарантируется стандартом. На практике это будет иметь место, но было бы гораздо лучше использовать значение true напрямую вместо ненужного предположения.

  3. В C ++ просто инициализируйте переменную нулями, чтобы все обнулились, например, bool chk[3][3] = {}; или используйте std::fill для заполнения массива заданным значением, например, fill( &chk[0][0], &chk[0][0] + 9, true );.


Приложение: чтобы быть педантичным, в пункте 1 есть предположение, что bool равен 1 байту. Это также предположение, которое имеет место на практике, но не гарантируется стандартом. К счастью, это не проблема для использования std::fill.

0 голосов
/ 03 сентября 2018

sizeof(chk[0]) равно sizeof(bool[3]), что явно отличается от sizeof(chk[0][0]), равного sizeof(bool).

С memset(chk, 1, 9*sizeof(chk[0])); вы пишете за пределы массива chk и получаете неопределенное поведение.

...