Почему вызов макроса C пожирает фигурные скобки? - PullRequest
8 голосов
/ 27 марта 2019

Рассмотрим:

#define TEST(x) x
int arr[2] = TEST({1, 2});

Я ожидаю, что он будет предварительно обработан в int arr[2] = {1, 2};

Вместо этого, как gcc, так и clang жалуются. gcc 7.3.0:

./test.c:2:25: error: macro "TEST" passed 2 arguments, but takes just 1
 int arr[2] = TEST({1, 2});

лязг 3.8.1:

./test.c:2:23: error: too many arguments provided to function-like macro invocation
int arr[2] = TEST({1, 2});

Я не смог найти упоминаний о фигурных скобках, специально обрабатываемых в стандартном разделе языка C для макросов (6.10).

Почему это происходит?

1 Ответ

9 голосов
/ 27 марта 2019

Причина в том, что вызов разделяется запятой для поиска аргументов, игнорируя любые символы, такие как {и} (см. Цитату из стандарта ниже). Специально обрабатываются только обычные парены.

Таким образом, TEST({1, 2}) интерпретируется как передаваемый два аргумента, {1 и 2}. Действительно:

#define TEST(x, y) | x | y |
int arr[2] = TEST({1, 2});

Предварительно обработано в:

int arr[2] = | {1 | 2} |;

Раздел 6.10.3.11:

Последовательность токенов предварительной обработки, ограниченная внешними совпадающими скобками формирует список аргументов для функционально-подобного макроса. Индивидуальные аргументы в список разделен токенами предварительной обработки, но токенами предварительной обработки между соответствующими внутренними скобками не разделяйте аргументы. Если есть последовательности токены предварительной обработки в списке аргументов, которые в противном случае действовали бы как директивы предварительной обработки, 172) поведение не определено.

...