Каков синтаксис следующего определения c?

Следующий фрагмент взят из mac sdk signal.h:

#define sigemptyset(set)    (*(set) = 0, 0)

Просто интересно, что делает , 0)?

Я не думаю, что это соответствующая реализация. POSIX говорит, что это должна быть функция с прототипом int sigemptyset(sigset_t *set);. При использовании макросов они также должны проверять тип аргумента и предоставлять реализацию функции.

PSkocik 13.02.2023 16:11

@PSkocik: прототип функции присутствует в заголовочном файле и реализован в библиотеке, макрос допускает встроенное расширение, жертвуя проверкой типов, чтобы сократить несколько циклов.

chqrlie 13.02.2023 16:18

@chqrlie Проверка типов с помощью *(sigset_t*){set} была бы тривиальной для более новых C, у которых есть составные литералы. Можно сделать и с древними функциями C: *(0?(sigset_t*)0:(set)). Для codegen макрос, конечно, лучше, чем вызов функции для такой тривиальной вещи, но ненужные отклонения от стандарта меня немного раздражают (что иронично, потому что я даже не очень люблю стандарты). В любом случае, хороший ответ. +1

PSkocik 13.02.2023 16:29

@PSkocik: интересные способы проверки типов в макросах без множественной оценки и расширений выражений операторов!

chqrlie 13.02.2023 16:38
Типы данных JavaScript
Типы данных JavaScript
В JavaScript существует несколько типов данных, включая примитивные типы данных и ссылочные типы данных. Вот краткое объяснение различных типов данных...
Как сделать движок для футбольного матча? (простой вариант)
Как сделать движок для футбольного матча? (простой вариант)
Футбол. Для многих людей, живущих на земле, эта игра - больше, чем просто спорт. И эти люди всегда мечтают стать футболистом или менеджером. Но, к...
Знайте свои исключения!
Знайте свои исключения!
В Java исключение - это событие, возникающее во время выполнения программы, которое нарушает нормальный ход выполнения инструкций программы. Когда...
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик Модуль flexbox, также известный как гибкий модуль разметки box, помогает эффективно проектировать и...
Введение в раздел "Заголовок" в HTML
Введение в раздел "Заголовок" в HTML
Говорят, что лучшее о человеке можно увидеть только изнутри, и это относится и к веб-страницам HTML! Причина, по которой некоторые веб-страницы не...
2
4
87
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Макрос расширяется до выражения с запятой: левый операнд, оцениваемый первым, устанавливает объект, на который указывает set, на 0, затем оценивается правый операнд, и его значение является значением всего выражения, следовательно: 0.

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

За исключением проверки типа, макрос эквивалентен:

#include <signal.h>

int sigemptyset(sigset_t *set) {
    *set = 0;
    return 0;
}

Обратите внимание, что заголовочный файл <signal.h> также содержит прототип этой функции:

int sigemptyset(sigset_t *);

Тот же трюк используется для других функций в заголовочном файле, для которых , 0) необходим, чтобы выражение оценивалось как 0 с типом int:

#define sigaddset(set, signo)   (*(set) |= __sigbits(signo), 0)
#define sigdelset(set, signo)   (*(set) &= ~__sigbits(signo), 0)
#define sigemptyset(set)        (*(set) = 0, 0)
#define sigfillset(set)         (*(set) = ~(sigset_t)0, 0)

Я бы добавил, что оператор запятая здесь не нужен, потому что левое выражение равно 0, но тот же шаблон, вероятно, используется для других макросов, заменяющих связанные функции, такие как sigfillset или sigaddset, где выражение присваивания не равно 0.

Bodo 13.02.2023 16:07

Тот же шаблон действительно используется для других макросов в <signal.h>, и использование , 0) приводит к тому, что выражение оценивается как 0 с типом int без приведения. sigset определяется как __uint32_t, определение макроса как #define sigemptyset(set) (*(set) = 0) будет иметь тип unsigned, а определение его как #define sigemptyset(set) ((int)(*(set) = 0)) не лучше, чем использование оператора запятой.

chqrlie 13.02.2023 16:09

В этом выражении

(*(set) = 0, 0)

Используется оператор запятая.

Результат выражения равен 0.

В качестве побочного эффекта объекту, на который указывает указатель set, присваивается значение 0.

Из стандарта C (оператор запятой 6.5.17)

2 Левый операнд оператора запятой оценивается как пустота выражение; существует точка последовательности между его оценкой и тем, что правого операнда. Затем оценивается правый операнд; результат имеет свой тип и значение.

Другие вопросы по теме