Подтвердить что ты не робот

Почему memset() неправильно инициализирует int?

Почему выводится следующая программа 84215045?

int grid[110];
int main()
{
    memset(grid, 5, 100 * sizeof(int));
    printf("%d", grid[0]);
    return 0;
}
4b9b3361

Ответ 1

memset устанавливает каждый байт буфера назначения в указанное значение. В вашей системе int - четыре байта, каждый из которых равен 5 после вызова memset. Таким образом, grid[0] имеет значение 0x05050505 (шестнадцатеричное), которое 84215045 в десятичной форме.

Некоторые платформы предоставляют альтернативные API для memset, которые пишут более широкие шаблоны в буфер назначения; например, в OS X или iOS, вы можете использовать:

int pattern = 5;
memset_pattern4(grid, &pattern, sizeof grid);

чтобы получить поведение, которое вы, похоже, ожидаете. На какой платформе вы нацеливаетесь?

В С++ вы должны просто использовать std::fill_n:

std::fill_n(grid, 100, 5);

Ответ 2

memset(grid, 5, 100 * sizeof(int));

Вы устанавливаете 400 байт, начиная с (char*)grid и заканчивая на (char*)grid + (100 * sizeof(int)), на значение 5 (здесь необходимы приведения, потому что memset имеет дело в байтах, тогда как арифметика указателя имеет дело с objects.

84215045 в шестнадцатеричном состоянии 0x05050505; поскольку int (на вашей платформе/компилятор/etc.) представляется четырьмя байтами, когда вы печатаете его, вы получаете "четыре пятых".

Ответ 3

memset - это установка байтов, а не значений. Один из многих способов задания значений массива в С++ - std::fill_n:

std::fill_n(grid, 100, 5);

Ответ 4

Не используйте memset.

Вы устанавливаете каждый байт [] в памяти на значение 5. Каждый int имеет длину 4 байта [5][5][5][5], который компилятор правильно интерпретирует как 5 * 256 * 256 * 256 + 5 * 256 * 256 + 5 * 256 + 5 = 84215045. Вместо этого используйте цикл for, который также не требует sizeof(). В общем случае sizeof() означает, что вы делаете что-то трудное.

for(int i=0; i<110; ++i)
    grid[i] = 5;

Ответ 5

Ну, memset записывает байты с выбранным значением. Поэтому int будет выглядеть примерно так:

00000101 00000101 00000101 00000101

который затем интерпретируется как 84215045.

Ответ 6

Вы на самом деле не сказали, что хотите сделать своей программе.

Предполагая, что вы хотите установить каждый из первых 100 элементов grid в 5 (и игнорировать несоответствие 100 vs. 110), просто выполните следующее:

for (int i = 0; i < 100; i ++) {
    grid[i] = 5;
}

Я понимаю, что вы обеспокоены скоростью, но ваша забота, вероятно, неуместна. С одной стороны, memset(), вероятно, будет оптимизирован и, следовательно, быстрее, чем простой цикл. С другой стороны, оптимизация, вероятно, будет состоять из записи более одного байта за раз, что и делает этот цикл. С другой стороны, memset() - это петля; запись цикла явно, а не захоронение в вызове функции не изменяет этого. С другой стороны, даже если цикл медленный, это вряд ли имеет значение; сосредоточиться на написании четкого кода и подумать об оптимизации, если фактические измерения указывают на существенную проблему с производительностью.

Вы потратили на несколько порядков больше времени на постановку вопроса, чем ваш компьютер проведет настройку grid.

Наконец, прежде чем я выйду из рук (слишком поздно!), не имеет значения, насколько быстр memset(), если он не делает то, что вы хотите. (Не устанавливать grid вообще еще быстрее!)

Ответ 7

Поскольку memset пишет байты, я обычно использую его для установки массива int равным нулю:

int a[100];
memset(a,0,sizeof(a));

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

char a[100];
memset(a,'*',sizeof(a));

что больше, массив int также может быть установлен на -1 с помощью memset:

memset(a,-1,sizeof(a));

Это потому, что -1 является 0xffffffff в int и равен 0xff в char (байт).

Ответ 8

Этот код был протестирован. Вот способ memset массива Integer со значением от 0 до 255.

MinColCost=new unsigned char[(Len+1) * sizeof(int)];

memset(MinColCost,0x5,(Len+1)*sizeof(int));

memset(MinColCost,0xff,(Len+1)*sizeof(int));