Я хочу увеличить массив во время выполнения (без указания длины с помощью macos)
у меня есть следующие вопросы
Я попробовал следующий код (и ожидал 012
в качестве вывода), но получил 000
#include <stdlib.h>
#include <stdio.h>
int main()
{
int *arr = NULL;
size_t n = 0;
for (int i = 0; i < 3; ++i) {
arr = realloc(arr, (n + 1) * sizeof *arr);
arr[n++] = i;
printf("%d", *arr);
}
}
*arr — первый элемент в arr
... или printf( "%d: %d and n = %d\n", i, arr[i], n );
Полезно показывать ссылку вместо черного ящика. (PS: Престижность за использование realloc()
без типичного первого malloc()
. Молодец!) И... Не забудьте free()
, чтобы быть чистым... :-)
Предложение: звонки на realloc
платные. Увеличьте свой массив в два раза, а не увеличивайте его каждый раз на единицу, чтобы свести к минимуму перераспределение.
@ecjb Подробно, в C массив не может изменить размер после его определения. Размер выделения памяти для хранения массива может меняться.
еще одна вещь, вы должны проверить возвращаемое значение realloc
, чтобы убедиться, что это удалось, прежде чем пытаться записать в память (вы в настоящее время надеетесь), которую он вам дал.
@yano Достоин «ответа», демонстрирующего, что исходный указатель не должен быть перезаписан вызовом функции ???
@Chris: использование коэффициента роста 1,5 вместо 2 может быть лучше. См. этот вопрос для получения дополнительной информации: Какова идеальная скорость роста для динамически выделяемого массива?
@ Fe2O3 уже ответил, но, возможно, это можно было бы включить в ответ ниже.
У ОП в основном это есть.
Он просто печатает первый элемент каждый раз.
// printf("%d", *arr);
printf("%d", arr[n-1]);
можно ли это сделать с массивом?
Нет. В C массив не может изменить размер после его определения.
Однако размер памяти, выделенной и на которую ссылается указатель, может измениться.
То, как вы перераспределяете массив, прекрасно, хотя и неэффективно. Причина, по которой вы не получаете ожидаемого результата, заключается в том, что вы выводите первый элемент 3 раза.
Рекомендуется размещать массивы за один раз, если вы заранее знаете конечную длину, в других случаях, когда большие массивы необходимо перераспределять на лету, рекомендуется перераспределять с использованием возрастающих размеров в геометрической прогрессии:
Вот пример использования золотого сечения:
#include <stdlib.h>
#include <stdio.h>
int main() {
char *arr = NULL;
size_t size = 0;
size_t pos = 0;
int c;
while ((c = getchar()) != EOF) {
if (pos + 1 > size) {
// increase size by a ratio of 1.625
// with an offset to handle the initial case without a test
size_t new_size = size + (size >> 1) + (size >> 3) + 32;
char *new_arr = realloc(arr, sizeof(*arr) * new_size);
if (new_arr == NULL) {
fprintf(stderr, "cannot reallocate array for %zu bytes\n", new_size);
free(arr);
return 1;
}
arr = new_arr;
size = new_size;
}
arr[pos++] = c;
}
if (arr == NULL) {
fprintf(stderr, "empty file\n");
return 1;
}
arr[pos] = '\0';
char *new_arr = realloc(arr, sizeof(*arr) * (pos + 1));
if (new_arr != NULL) {
arr = new_arr;
size = pos + 1;
}
/* more code to handle full buffer */
free(arr);
return 0;
}
size + (size >> 1) + (size >> 3)
прикольно, такое ощущение, что я нашла золотую монету. Просто из любопытства, почему число 32
. Просто произвольно? Не похоже, что это имеет какое-либо последующее значение (не учитывая тот факт, что оно функционирует как начальное значение, если size == 0
).
@ErdalKüçük: правильно, + 32
- это простое смещение для обработки исходного случая без ветвей.
Ваш код
realloc
в порядке (простой, но хороший). Вы хотите:printf(" %d",arr[n - 1]);
печатать текущий элемент, а не [всегда] первый.