Home > Enterprise >  How do function renaming macros work, and should one use them?
How do function renaming macros work, and should one use them?

Time:09-29

Everyone knows about classic #define DEFAULT_VALUE 100 macro where the preprocessor will just find the "token" and replace it with whatever the value is.

The problem I am having is understanding the function version of this #define my_puts(x) puts(x). I have K&R in front of me but I simply cannot find a suitable explanation. For instance:

  • why do I need to supply the number of arguments?
  • why can their name be whatever?
  • why don't I have to supply the type?

But mainly I would like to know how this replacement functions under the hood.

In the back of my mind I think I have a memory of someone saying somewhere that this is bad because there are no types.

In short, I would like to know if it is safe and secure to use macros to rename functions (as opposed to the alternative of manually wrapping the function in another function).

Thank you!

CodePudding user response:

The problem I am having is understanding the function version of this #define my_puts(x) puts(x).

Part of your confusion might arise from thinking of this variety as a "function renaming" macro. A more conventional term is "function-like", referring to the form of the macro definition and usage. Providing aliases for function names or converting from one function name to another is a relatively minor use for this kind of macro.

Such macros are better regarded more generally, simply as macros that accept parameters. From that standpoint, your specific questions have relatively clear answers:

  • why do I need to supply the number of arguments?

You are primarily associating parameter names with the various positions in the macro's parameter list. This is necessary so that the preprocessor can properly expand the macro. That the number of parameters is thereby conveyed (except for variadic macros) is of secondary importance.

  • why can their name be whatever?

"Whatever" is a little too strong, but the answer is that the names of macro parameters are significant only within the scope of the macro definition. The preprocessor substitutes the actual arguments into each expansion in place of the parameter names whenever it expands the macro. This is analogous to bona fide functions, actually, so I'm not really sure why this particular uncertainty arises for you.

  • why don't I have to supply the type?

Of the macro? Because to the extent that macros have a type, they all have the same one. They all expand to sequences of zero or more tokens. You can view this as a source-to-source translation. The resulting token sequence will be interpreted by the compiler at a subsequent stage in the process.

But mainly I would like to know how this replacement functions under the hood.

Roughly speaking, wherever the name of an in-scope function like macro appears in the source code followed by a parenthesized list of arguments, the macro name and argument list are replaced by the expansion of the macro, with the macro arguments substituted appropriately.

For example, consider this function-like macro, which you might see in real source code:

#define MIN(x, y) (((x) <= (y)) ? (x) : (y))

Within the scope of that definition, this code ...

n = MIN(10, z);

... expands to

n = (((10) <= (z)) ? (10) : (z));

Note well that

  • the function-like macro is not providing function alias in this case.
  • the macro arguments are substituted into the macro expansion wherever they appear as complete tokens in the macro's defined replacement text.

In the back of my mind I think I have a memory of someone saying somewhere that this is bad because there are no types.

Well, there are no types declared in the macro definition. That doesn't prevent all the normal rules around data type from applying to the source code resulting from the preprocessing stage. Both of these factors need to be taken into account. In some ways, the MIN() macro in the above example is more flexible than any one function can be be. Is that bad? I don't mean to deny that there are arguments against, but it's a multifaceted question that is not well captured by a single consideration or a plain "good" vs. "bad" evaluation.

In short, I would like to know if it is safe and secure to use macros to rename functions (as opposed to the alternative of manually wrapping the function in another function).

That's largely a different question from any of the above. The semantics of function-like macros are well-defined. There is no inherent safety or security issue. But function-like macros do obscure what is going on, and thereby make it more difficult to analyze code. This is therefore mostly a stylistic issue.

Function-like macros do have detractors these days, especially in the C community. In most cases, they have little to offer to distinguish themselves as superior to functions.

  •  Tags:  
  • c
  • Related