Данное диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Это правило актуально только для C. Если формальный параметр функции объявлен как массив с фиксированным размером, передаваемый в качестве фактического аргумента массив должен иметь размер не меньше, чем размер массива, принимаемый функцией.
В языке C передача массива в функцию происходит через передачу указателя на его начало, поэтому в такую функцию возможно передать массив любого размера. Однако, использование указателя в качестве формального параметра ухудшает понимание интерфейса функции – становится непонятно, работает она с одним элементом или с массивом.
Чтобы указать, что функция работает именно с некоторым количеством элементов, ее формальный параметр объявляется как массив, при этом размер часто указывается при помощи макроса. Макрос затем используется для обхода элементов массива:
#define ARRAY_SIZE 32 void foo(int arr[ARRAY_SIZE]) { for (size_t i = 0; i < ARRAY_SIZE; ++i) { // Do something with elements } }
Надо помнить, что такой массив по-прежнему является указателем. Следовательно, существует возможность передать массив с меньшим числом элементов, что может привести к выходу за его границы, что является неопределенным поведением:
#define ARRAY_SIZE 32 void foo(int arr[ARRAY_SIZE]); void bar() { int array1[32] = { 1, ...., 32 }; int array2[28] = { 1, ...., 28 }; foo(array2); // <= }
В данном примере функция получила массив неподходящего размера. Правильным вариантом может быть:
#define ARRAY_SIZE 32 void foo(int arr[ARRAY_SIZE]); void bar() { int array1[32] = { 1, ...., 32 }; int array2[28] = { 1, ...., 28 }; foo(array1); // <= }
Другим вариантом может быть изменение числа элементов переданного в функцию массива и заполнение добавленных элементов значениями по умолчанию:
#define ARRAY_SIZE 32 void foo(int arr[ARRAY_SIZE]); void bar() { int array1[32] = { 1, ...., 32 }; int array2[32] = { 1, ...., 28 }; // <= foo(array2); }
Если функция обрабатывает массивы разного размера, то правило разрешает использовать в качестве аргумента функции массив произвольного размера. Подразумевается, что размер массива будет передан иным способом, например так:
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) void foo(int arr[], size_t count); void bar() { int array1[] = { 1, 2, 3, 4, 5 }; int array2[] = { 10, 20, 30 }; foo(array1, ARRAY_SIZE(array1)); foo(array2, ARRAY_SIZE(array2)); }
Данная диагностика классифицируется как:
|