Как вы сами отметили, NONNULL
и MALLOC
- это просто макросы.Их замена начинается с __attribute__
, которое является ключевым словом расширения компилятора, используемым для определения атрибутов в функции.
__VA_ARGS__
является заменой переменного числа аргументов в макросе (объявлено с ...
).Таким образом, это объявление:
void opts_set_crl(opts_t *, const char *) NONNULL(1,2);
преобразуется препроцессором (до того, как его увидит компилятор) в:
void opts_set_crl(opts_t *, const char *) __attribute__((nonnull(1,2)));
Что это эффективно делает, так это предотвращает появление первого и второго параметров NULL
.Если вы посмотрите документацию компилятора, который поддерживает это расширение, например gcc или clang , вы найдете полное описание.
Другой атрибут, malloc
из руководства GNU :
Это говорит компилятору, что функция подобна malloc, т.е. что указатель P, возвращаемый функцией, не может псевдоним любого другого указателя, допустимого, когдафункция возвращает, и, кроме того, в любом хранилище, адресуемом P., нет указателей на действительные объекты.
Использование этого атрибута может улучшить оптимизацию.Такие функции, как malloc и calloc, имеют это свойство, поскольку они возвращают указатель на неинициализированное или обнуленное хранилище.Однако такие функции, как realloc, не имеют этого свойства, поскольку они могут возвращать указатель на хранилище, содержащее указатели.