Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a C macro invocation eat up curly braces?

Consider:

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

I would expect it to be preprocessed into int arr[2] = {1, 2};

Instead, both gcc and clang complain. gcc 7.3.0:

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

clang 3.8.1:

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

I couldn't find any mention of curly braces being treated specially in the C language standard section on macros (6.10).

Why does this happen?

like image 594
sinelaw Avatar asked Mar 27 '19 12:03

sinelaw


People also ask

Why curly braces are used in C program?

In programming, curly braces (the { and } characters) are used in a variety of ways. In C/C++, they are used to signify the start and end of a series of statements. In the following expression, everything between the { and } are executed if the variable mouseDOWNinText is true.

Why does Python not use curly braces?

Those that get used to the Python way of doing things tend to start seeing curly braces as unnecessary line noise that clutters code. On the other hand, 'the whitespace thing' is possibly the single biggest reason why some developers refuse to even try Python.

What do curly braces mean in Python?

In Python, curly braces are used to define a data structure called a dictionary (a key/value mapping), while white space indentation is used to define program blocks.

What loop is required for curly braces?

If the number of statements following the for/if is single you don't have to use curly braces. But if the number of statements is more than one, then you need to use curly braces.


1 Answers

The reason is that the invocation is split by comma to find the arguments, ignoring any characters such as { and } (see below for quote from the standard). Only regular parens are treated specially.

So TEST({1, 2}) is interpreted as being passed two arguments, {1 and 2}. Indeed:

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

Is preprocessed into:

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

Section 6.10.3.11:

The sequence of preprocessing tokens bounded by the outside-most matching parentheses forms the list of arguments for the function-like macro. The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate arguments. If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, 172) the behavior is undefined.

like image 181
sinelaw Avatar answered Sep 24 '22 00:09

sinelaw