Данное диагностическое правило основано на руководстве 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));
}
Данная диагностика классифицируется как:
|