Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Это правило актуально только для C.
Константа нулевого указателя должна быть получена путём раскрытия макроса NULL, определяемого имплементацией стандартной библиотеки, в случаях, когда эта константа:
!= или ==, где другой операнд — это указатель;?:), где третий операнд это — указатель;?:), где второй операнд — это указатель.Использование макроса NULL вместо константы 0 обеспечивает явное разделение семантики указателей и числовых значений, что исключает неоднозначность при чтении кода.
Примечание. Допускается использование константы нулевого указателя в виде (void*)0 даже если она не является результатом раскрытия макроса NULL.
Пример некорректного кода:
// Declaring structure in another file
struct Device {
void* config;
int status;
};
int updateDevice(struct Device* dev, int newStatus) {
// ....
// Here is a large fragment of code...
// ....
if (dev == 0) { // <=
return 0;
}
if (newStatus == STATUS_RESET) {
dev->config = 0; // <=
dev->status = newStatus;
return 1;
}
return 0;
}
В примере вместо NULL используется константа 0. На первый взгляд может показаться, что работа происходит с числами, а не с указателями. Для того чтобы избежать неоднозначности в трактовке выражений dev == 0 и dev->config = 0, рекомендуется заменить константу 0 на макрос NULL или выражение (void *)0.
Корректный код:
#include <stddef.h>
int updateDevice(struct Device* dev, int newStatus) {
// ....
// Here is a large fragment of code...
// ....
if (dev == NULL) { // ok
return 0;
}
if (newStatus == STATUS_RESET) {
dev->config = NULL; // ok
dev->status = newStatus;
return 1;
}
return 0;
}
Исключение. Инициализатор {0} может быть использован для инициализации объекта агрегатного типа или объединения, содержащего указатели.
Пример корректного кода:
typedef struct EXAMPLE_STRUCT
{
void* ptr;
} tExStruct;
tExStruct ya = { 0 }; // ok
Данная диагностика классифицируется как:
|