Предопределенный макрос используется в качестве объекта

Вы используете стандартные макросы библиотеки, такие как assert и errno как объекты

Описание

Предопределенный макрос, используемый в качестве объекта, происходит, когда вы используете определенные идентификаторы способом, который требует, чтобы основной объект присутствовал. Эти идентификаторы заданы как макросы. Стандарт C не позволяет вам переопределять их как объекты. Вы используете идентификаторы таким способом, которым не может произойти макрорасширение идентификаторов.

Например, вы отсылаете к внешней переменной errno:

extern int errno;
Однако errno не происходит как переменная, но макрос.

Дефект применяется к ним макросы: assert, errno, math_errhandling, setjmp, va_arg, va_copy, va_end и va_start. Средство проверки ищет дефект только в исходных файлах (не заголовочные файлы).

Риск

Стандарт C11 (Секунда. 7.1.4), позволяет вам переопределять большинство макросов как объекты. Чтобы получить доступ к объекту а не макросу в исходном файле, вы делаете один из них:

  • Повторно объявите идентификатор как внешнюю переменную или функцию.

  • Для подобных функции макросов заключите имя идентификатора в круглые скобки.

При попытке использовать эти стратегии макросов, которые не могут быть переопределены как объекты, ошибка происходит.

Фиксация

Не используйте идентификаторы таким способом, которым подавлено макрорасширение.

  • Не повторно объявляйте идентификаторы как внешние переменные или функции.

  • Для подобных функции макросов не заключайте макро-имя в круглые скобки.

Примеры

развернуть все

#include<assert.h>
typedef void (*err_handler_func)(int);

extern void demo_handle_err(err_handler_func, int);

void func(int err_code) {
    extern void assert(int);   
    demo_handle_err(&(assert), err_code);
}

В этом примере макрос assert переопределен как внешняя функция. Когда передано в качестве аргумента к demo_handle_err, идентификатор assert заключен в круглые скобки, который подавляет использование макроса assert.

Исправление — использует assert в качестве макроса

Одно возможное исправление должно непосредственно использовать макрос assert от assert.h. Различная реализация функционального demo_handle_err непосредственно использует макрос assert вместо того, чтобы брать адрес функции assert.

#include<assert.h>
void demo_handle_err(int err_code) {
    assert(err_code == 0);                   
}

void func(int err_code) {
    demo_handle_err(err_code);          
}

Информация о результате

Группа: Программирование
Язык: C | C++
Значение по умолчанию: на
Синтаксис командной строки: MACRO_USED_AS_OBJECT
Влияние: низко

Введенный в R2018a