Этот вопрос возник из-за замечания Эрика Постпишила, сделанного в другом потоке.
Мне сложно понять использование массивов переменной длины (VLA) в качестве параметров функции:
- Размер массива не проверяется.
- Размер массива не может быть восстановлен из массива, потому что стандартный тип настройки array -> указатель также применяется для VLA, как демонстрируют вызовы
sizeof()
ниже; даже если было бы вполне возможно передать весь массив в стек, точно так же, как VLA создаются в стеке при их определении. - Размер необходимо передавать как дополнительный параметр, как и в случае указателей.
Так почему же язык позволяет объявлять функцию с параметрами VLA, если они не дают никаких преимуществ и настраиваются, как любой другой аргумент массива для указателя? Почему выражение размера оценивается, если оно не используется языком (например, для проверки размера фактического аргумента) и не может быть получено внутри функции (для этого все равно необходимо передать явную переменную) ??
Чтобы прояснить, что меня сбивает с толку, рассмотрите следующую программу (живой пример здесь). Все объявления функций явно эквивалентны. Но, как указал Эрик в другом потоке, выражение размера параметра в объявлении функции оценивается во время выполнения. Выражение размера не игнорируется.
Мне неясно, какая польза от этого, потому что размер и его оценка не имеют никакого эффекта (помимо возможных побочных эффектов). В частности, повторюсь, эта информация не может использоваться кодом внутри функции. Наиболее очевидным изменением было бы передать VLA в стеке подобных структур. В конце концов, они обычно также находятся в стеке на стороне вызывающего. Но, как и в случае с массивами постоянной длины, тип настраивается уже во время объявления на указатель, все объявления ниже эквивалентны. Тем не менее вычисляется бесполезное и отброшенное выражение размера массива.
#include <stdio.h>
// Nothing to see here.
extern void ptr(int *arr);
// Identical to the above.
extern void ptr(int arr[]);
// Still identical. Is 1 evaluated? Who knows ;-).
extern void ptr(int arr[1]);
// Is printf evaluated when called? Yes.
// But the array is still adjusted to a pointer.
void ptr(int arr[printf("Call-time evaluation of size parameter\n")]){}
// This would not compile, so the declarations above must be equivalent.
// extern void ptr(int **p);
int main()
{
ptr(0);
ptr(0);
return 0;
}