Стандарт безопасного кодирования CERT включает item (API05-C), который поощряет использование соответствующих параметров массива, что является рекомендацией, которую я реализовал во многих частях моего кода (скрытых за макрос для компиляторов, которые их не поддерживают).
Для тех, кто не знает, соответствующий параметр массива выглядит примерно так:
void foo(int length, char data[length]);
API05-C предоставляет дополнительную информацию.
Многие компиляторы не любят массивы переменной длины (не зря). C11 понижает их уровень с обязательных (как в C99) до необязательных (компиляторы должны определять __STDC_NO_VLA__
, если они не реализованы). MSVC категорически не поддерживает их. IAR прячет их за переключателем (--vla
). GCC и clang предупредят вас о них, если вы спросите (с -Wvla
или -Werror=vla
, если вы хотите получить ошибку).
Параметры согласованного массива не страдают от тех же проблем, что и «нормальные» массивы переменной длины; они не приводят к использованию стека переменных. Они просто сообщают компилятору, насколько велик существующий массив, который может находиться в стеке или куче.
Моя проблема в том, что каждый известный мне компилятор обрабатывает параметры согласованного массива как VLA. Это не такая уж большая проблема для таких компиляторов, как MSVC, поскольку я могу просто определить свой макрос до нуля, но для таких компиляторов, как GCC и clang, я хочу использовать соответствующие параметры массива, но не хочу запускать -Wvla
диагностику.
Согласно API05-C (выделено автором):
Следовательно, объявление массива, которое служит аргументом функции, может иметь индекс, который является переменной или выражением. Аргумент массива понижается до указателя и, следовательно, не является массивом переменной длины (VLA). Соответствующие параметры массива могут использоваться разработчиками для указания ожидаемых границ массива. Эта информация может использоваться компиляторами или игнорироваться. Однако такие объявления полезны для разработчиков, поскольку они служат для документирования взаимосвязей между размерами массивов и указателями. Эта информация также может использоваться инструментами статического анализа для диагностики потенциальных дефектов.
Я отчаянно хочу, чтобы это было правдой, но я не могу найти соответствующие части C99 или C11.
Итак, основаны ли строго на стандартах C99 / C11, соответствуют ли параметры массива VLA? Или, говоря другими словами, действительно ли передача массива в качестве аргумента понижает его статус до указателя?
Разумеется, просьба указать соответствующие части спецификации.
type funcname (int a, int array[a]) { ... }
, тогда да,array
- это VLA (по определению это не может быть ничем другим,'a'
не является константой). Кроме того, вы можете предпочесть стандарт C11 (проект n1570), а не .pdf форма. - person David C. Rankin   schedule 22.04.2018does passing an array as an argument really demote it to a pointer?
Да. Было бы очень тяжело этого не сделать. - person Alceste_   schedule 22.04.2018C
в декларацииvoid fvla(int m, int C[m][m]);
VLA. (Нормативный) язык в 6.7.6.2 указывает, что да, эти параметры массива считаются массивами переменной длины. - person Cornstalks   schedule 22.04.2018sizeof
не работает с этими параметрами VLA, как с обычными VLA, потому что эти параметры VLA на самом деле являются просто указателями). - person Cornstalks   schedule 22.04.2018__STDC_NO_VLA__
, вы получите сообщение об ошибке (если вы не передадите--vla
, чтобы включить их). GCC и clang будут предупреждать о CAP, если вы передадите-Wvla
. - person nemequ   schedule 22.04.2018int (*ptr)[y] = malloc( sizeof( int[x][y] ) );
, или функции, подобные этим, рекомендованным CERT. - person Lundin   schedule 23.04.2018for (int i=0; i<100; i++) a[i] += b[i];
, компилятор может безопасно векторизовать цикл, если каждыйa
иb
идентифицируют начало массива, но не еслиa
иb
могут указывать на разные элементы одного и того же массива, например,b < a < b+100
. - person supercat   schedule 23.04.2018