#define FOO(x) bar, x never referenced in definition, what happens? - c-preprocessor

I found some legacy code with something similar to the following. Say I have the following definition:
#define FOO(x) bar
x is never referenced in the definition. So, does that mean that whatever text is placed within FOO() is irrelevant?
The code I'm looking at is scattered with calls such as FOO(someValue); I'm assuming the preprocessor is replacing the entire statement with simply bar, no matter what someValue is? A little thrown off by why x is present at all.

Yes, FOO(whatever) is completely replaced with bar in your example.
Macros like this are often seen in "configure-able" code, like:
#if defined(ENABLE_DEBUG_PRINT)
#define DEBUG_PRINT(msg) printf("Here's a message: %s\n", msg)
#else
#define DEBUG_PRINT(msg) /* empty */
#endif

Nothing special happens. Any occurrence of x in the macro definition is expanded to the value of the corresponding argument when the macro is expanded. If there is no such occurrence, it's not expanded (and the actual value of the argument is irrelevant).
As for why it's there, it may be that some past or potential future version of the macro might make some use of the argument. Perhaps it's one of several macros that take a single argument, and it's defined that way for consistency. It's impossible to tell without more context. But the macro definition is perfectly valid.

What happens is exactly what you thought would happen—the value is ignored.
I recommend running the preprocessor (gcc -E or cpp (possibly add -x c++ for c++)) to actually see what actually happens on your implementation instead of just guessing.

Yes, macro FOO() expands to bar regardless of its argument. This is not different in nature from how a function can ignore some or all of its parameters.
The macro may be a place holder for a possible future implementation that does use its argument, or a replacement for an older implementation that did. It may also be that the definition of macro FOO() is different in different places, and that some of the definitions use their argument. If it isn't any of those, nor similar, then it's just obfuscatory.

So, does that mean that whatever text is placed within FOO() is irrelevant?
Unless there's a conditionally-compiled alternative version of FOO() where x is actually used. You might that to only evaluate the expression x in the debug build, for instance.

This statement just consumes the x expression without using it.
For instance, if you want to stub some methods you can use that.

Related

Is there a tool that checks what predefined macros a C file depends on?

To avoid impossible situation one could reduce the problem to two cases.
Case 1
The first (simplest) case is situation where the preprocessor has a chance to detect it, that is there's a preprocessor directive that depends on a macro being predefined (that is defined before the first line of input) or not. For example:
#ifdef FOO
#define BAR 42
#else
#define BAR 43
#endif
depends on FOO being predefined or not. However the file
#undef FOO
#ifdef FOO
#define BAR 42
#endif
does not. A harder case would be to detect if the dependency actually does matter, which it doesn't in the above cases (as neither FOO or BAR affects the output).
Case 2
The second (harder) case is where successful compilation depends on predefined macros:
INLINE int fubar(void) {
return 42;
}
which is perfectly fine as far as the preprocessor is concerned whether or not ENTRY_POINT is predefined, but unless INLINE is carefully defined that code won't compile. Similarily we could in this case it might be possible to exclude cases where the output isn't affected, but I can't find an example of that. The complication here is that in the example:
int fubar(void) {
return 42;
}
the fubar being predefined can alter the successful compilation of this, so one would probably need to restrict it to cases where a symbol need to be predefined in order to compile successfully.
I guess such a tool would be something similar to a preprocessor (and C parser in the second case). The question is if there is such a tool? Or is there a tool that only handles the first case? Or none at all?
In C everything can be (re)defined, so there is no way to know in advance what is intended to be (re)defined. Usually some naming conventions helps us to figure out what is meant to be a macro (like upper-case). Therefore it is not possible to have such tool. Of course if you assume that the compilation errors are caused by missing macro definitions then you can use them to analyze what is missing.

Is there a way to 'escape' an ampersand in a C preprocessor macro?

I have a library I am porting from Windows to Linux, and I am required to make the minimal number of changes necessary.
There are some function calls in the library that I need to call variants of, with one less parameter and I am trying to use a macro to perform the substitutions.
The issue is that these calls are passing the address of a structure and I'm getting the error "error: "&" may not appear in macro parameter list"
For example, if the library has the following call:
foo(param1, &param2);
and I need to replace it with
foo_variant(&param2);
I am adding a conditional compile at the top of the file as follows:
#if defined LINUX_VARIANT
#define foo(param1, &param2) foo_variant(&param2)
#endif
Is there any way to "escape" the ampersand to avoid this error?
If not, I did see another post that mentioned that a pointer to the struct could be defined, and use the pointer instead of taking the structure's address, but I'd like to avoid that unless there is no other option.
Thanks ahead for any enlightenment!
Just forward the whole argument expression:
#define foo(param1, param2) foo_variant(param2)
Note that, due to limitations of the preprocessor, this macro will fail if any of the arguments contains commas.
Quentin's answer is correct, but to give a bit more background: the preprocessor will textually replace any foo(... with foo_variant(... and will also textually replace the parameters. If one parameter in the C source file has an ampersand, it will just see that as part of the parameter.
So the preprocessor cannot accept an ampersand in its definition, it can accept an ampersand in its expansion. With:
#if defined LINUX_VARIANT
#define foo(param1, param2) foo_variant(&param2)
#endif
then
foo(p1, p2);
will be replaced by
foo_variant(&p2);

Preventing incorrect macro expansion in gcc

Is there any way to prevent gcc from expanding a macro in this:
#define putc(a) fputc(a)
...
void _putc(char ch) {}
struct foo { void *(putc)(char ch); }
struct foo f = {_putc;}
(&f)->putc('X'); // this is an error because it gets expanded into fputc, which is very inappropriate.
I don't want to use #undef putc because it messes up other things.
Including <stdio.h> may or may not define macro functions. In either case, a real function is provided.
It's probably not the best idea to name a function pointer like a standard library function, but you can do it. To prevent macro expansion, you have basically three options:
#undef it. You said this would mess up other things, though this shouldn't be a problem -- a real function with that name still exists. For some functions, you may miss optimizations or warnings (for functions like printf, for example), however (depending on your compiler).
Don't include the header file and declare the function yourself. I mention this for sake of completeness rather than as a real suggestion. This doesn't work if you need a type definition provided only in the header you don't want to include.
Don't put an opening parenthesis after the macro name, as in
((&f)->putc)('X'); // or (f.putc)('X'); -- looking less confusing.

Using a #define-d list as input to a C preprocessor macro

In an example project, I defined the macro
#define FOO(x, y) x + y .
This works perfectly well. For example, FOO(42, 1337) is evaluated to 1379.
However, I now want to use another #define:
#define SAMPLE 42, 1337
When I now call FOO(SAMPLE), this won't work. The compiler tells me that FOO takes two arguments, but is only called with one argument.
I guess that the reason for this is that, although, the arguments of a macro are evaluated in advance of the function itself, that the preprocessor does not parse the whole instruction again after this evaluation. This is a similar to the fact that it is not possible to output additional preprocessor directives from a macro.
Is there any possibility to get the desired functionality?
Replacing the FOO macro with a C function is not a possibility. The original macro is located in third party code I cannot change, and it outputs a comma-separated list of values to be directly used in array initializers. Therefore, a C function cannot replicate the same behaviour.
If it is not possible to accomplish this task by using simple means: How would you store the (x, y) pairs in a maintainable form? In my case, there are 8 arguments. Therefore, storing the individual parts in separate #define-s is also not easy maintainable.
You're running into a problem where the preprocessor is not matching and expanding macros in the order you want. Now you can generally get it to do what you want by inserting some extra macros to force it to get the order right, but in order to that you need to understand what the normal order is.
when the compiler sees the name of a macro with arguments followed by a ( it first scans in that argument list, breaking it into arguments WITHOUT recognizing or expanding any macros in the arguments.
after parsing and separating the arguments, it then rescans each argument for macros, and expands any it finds withing the argument UNLESS the argument is used with # or ## in the macro body
it then replaces each instance of the argument in the body with the (now possibly expanded) argument
finally, it rescans the body for any OTHER macros that may exist with the body for expansion. In this one scan, the original macro WILL NOT be recognized and reexpanded, so you can't have recursive macro expansions
So you can get the effect you want by careful use of an EXPAND macro that takes a single argument and expands it, allowing you to force extra expansions at the right point in the process:
#define EXPAND(X) X
#define FOO(x,y) x + y
#define SAMPLE 42, 1337
EXPAND(FOO EXPAND((SAMPLE)))
In this case you first explicitly expand macros in the argument list, and then manually expand the resulting macro call afterwards.
Update by question poster
#define INVOKE(macro, ...) macro(__VA_ARGS__)
INVOKE(FOO, SAMPLE)
provides an extended solution that works without cluttering the code with EXPANDs.

Is it necessary to undef macros within function?

I've seen many times code like this:
void func(){
#define a ...
...
#undef a
}
Is the #undef necessary at all?
It is not necessary, but the scope of a #define is global after the line it was defined. It will not obey the function scope, if you are thinking it will.
It's not necessary. If the macro is meant to be used only inside the function, it's probably a good idea to #undef it. If you don't, that just means that the macro remains visible through the rest of the translation unit (source file).
Most macros are probably intended to be visible throughout a source file anyway, so usually the question doesn't arise.
When i declare a macro like you did inside the body of a function then i would #undef it at the end. Because most probably it is meant for that function body only.
In general it is always a good idea to #undef a macro when you know that the macro definition is not going to be used anytime later because the macro definition propagate to all other files which include the file having a macro.
That depends. It is only necessary if you want to ensure that a will not be potentially available at later points in your program depending on your logic. The define is now global (in the current translation unit)!
From gnu.org:
If a macro ceases to be useful, it may be undefined with the `#undef'
directive.
Additionally,
Once a macro has been undefined, that identifier may be redefined as a
macro by a subsequent `#define' directive. The new definition need not
have any resemblance to the old definition.
and
However, if an identifier which is currently a macro is redefined,
then the new definition must be effectively the same as the old one.
Two macro definitions are effectively the same if:
Both are the same type of macro (object- or function-like).
All the tokens of the replacement list are the same.
If there are any parameters, they are the same.
Whitespace appears in the same places in both. It need not be
exactly the same amount
of whitespace, though. Remember that comments count as
whitespace.

Resources