//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
В этот момент вы выделили вдвое больше памяти - пространство для десяти целых чисел в массиве, выделенном в стеке, и пространство для десяти целых чисел, выделенных в куче. В «настоящей» программе, которой нужно было выделять место для десяти целых чисел, а выделение стека было неправильным, выделение могло бы быть сделано следующим образом:
int *p = malloc(10 * sizeof(int));
Обратите внимание, что нет необходимости приводить возвращаемое значение из malloc(3)
. Я ожидаю, что вы забыли включить заголовок <stdlib>
, который бы правильно прототипировал функцию и дал вам правильный вывод. (Без прототипа в заголовке компилятор C предполагает, что функция вернет int
, и приведение заставляет его обрабатывать его как указатель. Вместо этого приведение не было необходимо в течение двадцати лет.)
Кроме того, будьте осторожны в изучении привычки sizeof(array)
. Это будет работать в коде, где массив размещен в том же блоке, что и ключевое слово sizeof()
, но fail при использовании так:
int foo(char bar[]) {
int length = sizeof(bar); /* BUG */
}
Это будет выглядеть правильно, но sizeof()
фактически увидит char *
вместо полного массива. Новая поддержка C Variable Length Array очень важна, но ее не следует путать с массивами, которые знают свой размер, доступный во многих других языках.
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
*p += sizeof(int);
Aha! Кто-то еще, кто имеет те же проблемы с указателями C, что и я! Я предполагаю, что вы писали в основном ассемблерный код, и вам приходилось увеличивать свои указатели самостоятельно? :) Компилятор знает тип объектов, на которые p
указывает (int *p
), поэтому он будет правильно перемещать указатель на правильное количество байтов, если вы просто напишите p++
. Если вы поменяете код на использование long
или long long
, или float
, или double
, или long double
, или struct very_long_integers
, компилятор всегда будет делать правильно с p++
.
.
i += sizeof(int);
}
Хотя это не неправильно , было бы, конечно, более идиоматичным переписать последний цикл немного:
for (i=0; i<array_length; i++)
p[i] = 5;
Конечно, вам придется хранить длину массива в переменной или #define
, но это проще сделать, чем полагаться на иногда привередливые вычисления длины массива.
Обновление
Прочитав другие (отличные) ответы, я понял, что забыл упомянуть, что, поскольку p
является вашей единственной ссылкой на массив, было бы лучше не обновлять p
, не сохраняя где-нибудь копию его значения , Моя небольшая «идиоматическая» перезапись позволяет обойти проблему, но не указывает на , почему использование подписки является более идиоматичным, чем увеличение указателя - и это одна из причин, почему подписка предпочтительнее. Я также предпочитаю подписку, потому что часто гораздо проще рассуждать о коде, в котором база массива не меняется. (Это зависит.)