Я хочу увеличить массив во время выполнения (без указания длины с помощью 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]); печатать текущий элемент, а не [всегда] первый.