Почему memset() неправильно инициализирует int?
Почему выводится следующая программа 84215045
?
int grid[110];
int main()
{
memset(grid, 5, 100 * sizeof(int));
printf("%d", grid[0]);
return 0;
}
Ответы
Ответ 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));