Вопрос или проблема
Я хочу создать указатель, который будет либо массивом, либо нулевым указателем. Что-то вроде
int * arr = (condition) ? int[var] : NULL
но, похоже, нет способа объявить безымянный, неинициализированный массив переменной длины.
Я знаю, что могу сделать это в несколько шагов, начиная с неинициализированного массива и позже устанавливая его в NULL
в зависимости от условия, но это кажется не элегантным.
Я также знаю, что могу использовать malloc()
, но в этом случае мне нужно вручную освобождать эту память.
Мне кажется, что, поскольку массив – это просто указатель на первый элемент, то то, что я хочу, не логически противоречит C, но я могу ошибаться.
Возможно ли достичь этого в стандартном C? Существует ли основная причина, по которой это не может работать?
Если бы массив был фиксированного размера, вы могли бы сделать это с помощью составного литерала:
int *arr = condition ? (int[5]){} : NULL;
Однако вы хотите использовать массив переменной длины. Такие массивы не могут быть инициализированы (до C23, в котором допускается пустая инициализация VLA и будет = {}
), и в результате для VLA не может быть создан составной литерал.
Вам придется придерживаться одного из альтернативных методов, которые вы предложили, либо создавая массив и устанавливая указатель отдельно:
int size = condition ? var : 1;
int a[size];
int *arr = condition ? a : NULL;
Либо использовать malloc
:
int *arr = condition ? malloc(var * sizeof *p) : NULL;
Ответ или решение
К сожалению, в стандартном C нет возможности создать указатель на массив переменного размера (VLA) напрямую в выражении при условии, которое вы описали. Давайте подробнее разберем вашу задачу и предложенные решения.
Проблема
Вы пытаетесь создать указатель arr
, который может указывать на массив переменного размера, созданный в зависимости от некоторого условия, или быть равным NULL
, если условие не выполняется. Вы правы в том, что в стандарте языка C нет прямой возможности инициализации VLA в едином выражении (за исключением C23, где появится возможность инициализации пустыми фигурными скобками для VLAs, но это еще не решает вашу задачу).
Возможные решения
1. Использование предварительных шагов
Вы можете создать массив и указатель в два этапа, как вы и упоминали:
int size = condition ? var : 1; // Определяем размер
int a[size]; // Создаем массив переменной длины
int *arr = condition ? a : NULL; // Указываем на массив или NULL
2. Использование malloc
Другим вариантом является использование динамического выделения памяти с помощью malloc
. Это решение более гибкое, так как размеры массивов могут быть определены во время выполнения, однако не забудьте освободить выделенную память после использования, чтобы избежать утечки памяти:
int *arr = condition ? malloc(var * sizeof(int)) : NULL;
if (arr == NULL && condition) {
// Обработка ошибки, если malloc не смог выделить память
}
Заключение
Таким образом, в стандартном C не существует способа напрямую создать указатель на VLA в зависимости от условия в одном выражении. Наилучший подход — это либо предварительное создание массива, либо использование динамического выделения памяти с malloc
. Оба этих метода имеют свои достоинства и недостатки, и выбор зависит от специфики вашего приложения и требований к управлению памятью.