2

Here is what confuses me:

To define a function-like macro, you use the same '#define' directive, but you put a pair of parentheses immediately after the macro name.

I believe this is to make the code stand out for people other than the author of the program. Like other rules of CAPS for macro names. But the following is where I get confused:

A function-like macro is only expanded if its name appears with a pair of parentheses after it. If you write just the name, it is left alone.

I disagreed instantly after reading it. And gcc -E verified that in the following code

#define FUNC display()

void display()
  {
    printf("Display\n");
  }

int main()
  {
    FUNC;
    return 0;
   }

The pre-processed output shows the content of the main() function as expected:

int main()
  {
    display();
    return 0;
  }

So what am I missing here? The pre-processor is for tokenizing the source, the macro expansion is a token and the above code was processed that way, the pre-processor isn't supposed to check anything or verify anything, it just dumps tokens. In that case what is the gcc manual trying to convey.

I am learning C programming, so I might be misunderstanding it a great deal as it frequently happens, I searched for a proper explanation and finally resorted to asking here. Please help me with this.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • 1
    So it looks like you are missing what "function-like" macro is. `FUNC` is not a function-like macro... – Eugene Sh. Oct 14 '16 at 14:25
  • 1
    No, I actually didn't understand this sentence properly. "A function-like macro is only expanded if its name appears with a pair of parentheses after it. If you write just the name, it is left alone." – Mendicant Bias Oct 14 '16 at 14:37

2 Answers2

11

When you define:

#define FUNC display()

FUNC is not a function-like macro; it is an object-like macro that expands to a function call.

A function-like macro looks like:

#define FUNC() display()

Now you must write FUNC() to invoke it. Or, more frequently, it will have arguments:

#define MIN(x, y) ((x) > (y) ? (x) : (y))

and that can be invoked with:

int min = MIN(sin(p), cos(q));

with cautions about the number of times the arguments are expanded.

See also getc() as macro and C standard library function definition. It includes the standard's explanation of why it is important that the simple name of a function-like macro without a following open parenthesis is not expanded, which is what the quote from the GCC manual is telling you.

When a function-like macro is defined, the open parenthesis must 'touch' the macro name:

#define function_like(a) …
#define object_like (…)

Because there's a space after object_like, the open parenthesis is part of the replacement text, not the start of an argument list. When the function-like macro is invoked, there may be spaces between the macro name and the argument list:

function_like (x)    // Valid invocation of function_like macro.

However, if you wrote:

int (function_like)(double a) { return asin(a) + 2 * atanh(a); }

this is not an invocation of the function-like macro because the token after function_like is not an open parenthesis.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Thanks, I was aware of the object-like and function-like macros. I just didn't understand a sentence properly, which is a very embarrassing thing. – Mendicant Bias Oct 14 '16 at 14:33
  • It happens — don't worry about it. It was a reasonable question, even if based on an easily fixed misunderstanding. – Jonathan Leffler Oct 14 '16 at 14:35
  • Thank you for the help, I really appreciate it. – Mendicant Bias Oct 14 '16 at 14:40
  • Nitpick: In `FUNC();` the `;` is merely the usual statement terminator and not part of invoking the macro. Macros in general don't need semicolons between them because they are expanded before parsing. Obviously, this one does because of what it expands to – trent Oct 14 '16 at 14:52
  • @trentcl: yeah — I've removed the semicolon. It was `FUNC();` in contrast to `FUNC;` as in the question, but it is probably better with the nit picked. Thanks. – Jonathan Leffler Oct 14 '16 at 15:20
  • That cleared a lot of things for me, I found the answer to my next question as well. Thank you very much. – Mendicant Bias Oct 14 '16 at 15:39
1

There are two kinds of macros. They differ mostly in what they look like when they are used.
Object-like macros resemble data objects when used, function-like macros resemble function calls.

You may define any valid identifier as a macro, even if it is a C keyword. The preprocessor does not know anything about keywords. This can be useful if you wish to hide a keyword such as const from an older compiler that does not understand it. However, the preprocessor operator can never be defined as a macro, and C++'s named operators cannot be macros when you are compiling C++.

prophet1906
  • 123
  • 7
  • Note that the standard says that there shall be no macros that redefine keywords in effect when you include any of the standard headers. – Jonathan Leffler Oct 14 '16 at 14:34
  • Depending on which bits of the standard library you use and where you put that Macro in your code, the program could compile fine. – prophet1906 Oct 14 '16 at 14:42