Примечание: эта версия этого ответа является результатом серьезной перезаписи. Некоторые претензии были удалены, а другие значительно изменены, чтобы сосредоточиться и лучше обосновать наиболее важные моменты.
Макросы Variadic и их переменные аргументы
[Спорная, много спорная позиция удалена. Это больше отвлекало, чем помогало.]
Предлагаемый макрос
Мне кажется, я нашел простое, компактное и стандартное решение:
#define is_empty(...) ( sizeof( (char[]){#__VA_ARGS__} ) == 1 )
Мы можем обойти любой вопрос неопределенности, рассмотрев эту вариацию:
#define is_empty(dummy, ...) ( sizeof( (char[]){#__VA_ARGS__} ) == 1 )
. Те же соображения применимы к интерпретации пустых против непустых переменных переменных здесь, как и в вашей исходной версии. В частности,
На основе C17 6.10.3.2/2 (оператор #): " Строка символов
литералом, соответствующим пустому аргументу, является """, я считаю, что
#__VA_ARGS__
всегда четко определено.
Я согласен. Здесь также важен раздел 6.10.3.1/2: «Идентификатор __VA_ARGS__
, встречающийся в списке замены, должен обрабатываться так, как если бы он был параметром [...].»
Объяснение макроса:
- Это создает составной массив символов литерала и инициализирует его, используя строковый литерал.
Да.
- Независимо от того, что передано макросу, все аргументы будут преобразованы в один длинный строковый литерал.
Да. __VA_ARGS__
рассматривается как a (один) параметр. Если имеется несколько переменных-переменных, это может повлиять на повторное сканирование, но оператор строкового преобразования действует в точке раскрытия макроса до повторного сканирования.
- Если список макросов пуст, строковый литерал станет "", который состоит только из нулевого терминатора и поэтому имеет размер 1.
Да.
- Во всех остальных случаях его размер будет больше 1.
Да. Это справедливо даже в случае двух аргументов с нулевым токеном в списке аргументов переменной, is_empty(dummy,,)
, где #__VA_ARGS__
будет расширяться до ","
. Это также верно в случае аргумента, состоящего из пустого строкового литерала, is_empty(dummy, "")
, где #__VA_ARGS__
будет расширяться до "\"\""
.
ОДНАКО , что все еще может не соответствовать вашим целям. В частности, вы не можете использовать его в директиве условной компиляции. Хотя sizeof
выражения обычно разрешены в выражениях целочисленных констант, таких как формы управляющих выражений таких директив,
Следовательно, если ваш макрос используется как или в управляющем выражении директивы условной компиляции, он будет оцениваться так, как если бы оператор sizeof
в нем был заменен на 0
, что приведет к недопустимому выражению.