Когда вы передаете массив как параметр функции в C, он «настраивается» на указатель. В C11 это § 6.7.6.3 ¶ 7:
Объявление параметра как «массива тип » должно быть скорректировано на «квалифицированный указатель на тип », где квалификаторы типа (если таковые имеются) - те, которые указаны в [ и ] деривации типа массива. Если ключевое слово static также присутствует в пределах [ и ] при выводе типа массива, то для каждого вызова функции указывается значение соответствующего фактического аргумента. должен обеспечить доступ к первому элементу массива, по крайней мере, с таким количеством элементов, как указано в выражении размера.
Тем не менее, вы можете сообщить компилятору и / или дополнительным инструментам (например, инструментам статического анализа), что другой параметр несет длину, но этот параметр должен прийти перед параметром массива. Это хорошая практика, чтобы войти в; см. API05-C в стандарте кодирования SEI CERT C для получения дополнительной информации.
Проблема в том, что компиляторы вроде как отстой. Во-первых, параметры согласованного массива разрешены только в C ≥ C99, поэтому, если предполагается, что ваш код строго C89 или что-то еще, они не будут работать.
Несмотря на то, что параметры согласованного массива (по сомнению) не являются массивами переменной длины , большинство компиляторов в основном воспринимают их как таковые, а поддержка компиляторов для VLA довольно нечеткая; C11 даже делает поддержку VLA необязательной. MSVC не реализует их вообще. GCC и Clang (по крайней мере) будут предупреждать, если вы используете их с включенным -Wvla
. В PGI есть ошибка, которая приводит к сбою компиляции. IAR также обрабатывает их как VLA и выдает предупреждение, если вы не включаете массивы переменной длины (поддержка отключена по умолчанию, но есть переключатель командной строки для их включения). Tiny C Compiler также выдает ошибку; IIRC, потому что он также считает их VLA.
Тем не менее, я все еще люблю их использовать. Это облегчает понимание кода, и интеллектуальные инструменты статического анализа могут использовать их для лучшей проверки вашего кода. Если вы хотите сделать свой код переносимым, вам нужно спрятать его за макросом, подобным , который у меня есть в Hedley .
Независимо от того, хотите ли вы использовать соответствующие параметры массива, вам нужно изменить свой код. Вы можете передать массивы как два аргумента или создать тип, который инкапсулирует как длину, так и массив ... два аргумента - определенно идиоматическое решение. Так что для вашего прототипа вы получите что-то вроде
// No conformant array parameters, just another parameter
float average(size_t n, float num[]);
// CAP
float average(size_t n, float num[n]);
// CAP with a macro
float average(size_t n, float num[ARRAY_PARAM(n)]);
sizeof(num)
все равно будет равно sizeof(float*)
(поскольку это то, что есть), но, по крайней мере, вы знаете, сколько элементов в массиве.