C preprocessor - concatenating strings without multiple resolving - c

I have a macro that points to another macro:
#define USART1 ((USART_TypeDef *) USART1_BASE)
#define PIPE1 USART1
I'm trying to add a static text which I will use as a function definition (USART1 becomes USART1_IRQHandler). I tried something like:
#define _IRQ(NAME) NAME ## _IRQHandler
void _IRQ(PIPE1)(void) {
//...
}
but the name resolves as PIPE1_IRQHandler instead of USART1_IRQHandler. Then I tried #NAME to get the value of PIPE1, but it had fully resolved to the most low-level representation:
((USART_TypeDef *) ((((uint32_t)0x40000000) + 0x10000) + 0x3800))
Is there any way to get USART1_IRQHandler?

No, there isn't.
Macro arguments which participate in concatenation (##) and stringification (#) are not expanded at all in the course of replacing the macro with its definition. Consequently, it is common to pass arguments through an indirect macro so that they will be expanded fully befire being passed to the macro which concatenates or stringifies them.
There is no mechanism for partial expansion. It's basically all or nothing.
If you want to build up complicated chains of macro substitution, you need to avoid using words both as macros and as token pieces, as in your example.

Related

Operator to convert to string

Why does the code snippet 1 works but NOT code snippet 2
Code Snippet 1:
#define mkstr(x) #x
int main(void)
{
printf(mkstr(abc));
return (0);
}
Code Snippet 2:
int main(void)
{
printf(#abc);
return(0);
}
The first snippet works because it has a function-like macro defined in which you put anything, the value is correctly assigned as a constant.
OTOH, the second one has a syntactic error because the compiler doesn't expects that parameter passed in printf(). Thus, the # is meaningless there.
Commands starting with the # symbol are called Macros in C and C++. Macros are blocks of code that are named and referenced with that name.
There are 2 popular types of macros - the Object-like and the function-like. The one you're using is the function-like macro.
The Preprocessor is responsible for replacing macro calls with the actual object/function calls.
The statement in Snippet 1
#define mkstr(x) #x
The above macro uses a special feature called the stringizing. The # before the x specifies that the input parameter should be treated as is, ie. converted to a string constant, thereby returning a string equivalent of what is passed.
On the contrary, when you call the below code in Snippet 2
printf(#abc);
doesn't mean anything. It's a compiler error as #s are not allowed in the middle or end of a statement (please not that # is allowed to be part of string such as "#1", or when used as a character literal as '#'). And thus any statement that starts with # becomes a macro.
Caution: Use of macros is discouraged. You can refer this answer on StackOverflow on why not to use them.
Refer the below resources to learn more about macros
Macro (The C Preprocessor) - GNU GCC
C Preprocessors and Macros - Programiz

Do function like macros need a mandatory parentheses? I am confused after referring the GCC cpp manual

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.
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.
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++.

Function-like C macro without parentheses

I have encountered the following debug macro in an embedded device codebase:
extern void DebugPrint(uint8_t *s);
#define DEBUG_MSG(x) do { PRINT_CURRENT_TIME; \
DebugPrint x ; } while(0)
Since there are no parentheses around x in the macro body (at the DebugPrint x part), all calls to this macro (all over the codebase) add another set of parentheses around strings:
DEBUG_MSG(("some debug text"));
Is there any reason to do this? Does it simplify optimizing away these calls in release builds, or something like that? Or is it just plain nonsense?
I thought perhaps there would be additional overloads of DebugPrint with more arguments, but there are none.
Here's a theory:
The preprocessor parses the arguments of a macro expansion in a way that mimics the compiler's expression parsing. In particular it parses terms in parentheses as a single argument.
So the DEBUG_MSG author's intention might have been to enforce the use of parentheses.
This might make sense when the DebugPrint print function would actually be a printf style variadic function. You could call the function with a single string literal or with a variable number of arguments:
DEBUG_MSG(("reached this point in code"));
DEBUG_MSG(("value of x = %i", x));
But this is pure speculation. Can't you just ask the author?
I believe that no. Macros are replaced by the compiler, so they have nothing to do with execution speeds. This:
#define MACRO(x) do_something(x)
MACRO("test");
Is no different than this
#define MACRO(x) do_something x
MACRO(("test"));
Since the compiler will replace them both with the same output:
do_something("test");
which will then compile to produce the same object code.

Embedding preprocessor directive into function name

I want to embed a preprocessor directive into a function name. Basically I want to make a macro that takes a preprocessor define as argument and concatenates it's defined VALUE to get a function name.
Basically this:
#define PREFIX foo
#define CALL(P, x) _##P_bar(x)
...then
CALL(PREFIX, x) should become _foo_bar(x)
Unfortunately this results in _P_bar instead of _foo_bar.
Is it possible to make it work as above?
The C standard defines special behavior for macro parameters immediately preceded and followed by ## operator. In such case they are not fully expanded. This is why your code did not behave as you expected. To further expand a parameter, you have to use it in a way that it is not immediately preceded or followed by ## operator. Try the following:
#define PREFIX foo
#define CALL2(P,x) _##P##_bar(x)
#define CALL(P, x) CALL2(P,x)
CALL(PREFIX, x)

How to pass a macro's result to another macro?

I have two macros in my C code the helps me to compose the name of certain variables. As an example, consider the following:
#define MACROA(name) A_##name
#define MACROB(name) B_##name
void *MACROB(MACROA(object));
So, I'm trying to declare a variable called B_A_object. However, this doesn't work and the compiler throws me the message:
object.c:27:21: error: a parameter list without types is only allowed in a function definition
void *MACROB(MACROA(object));
^
object.c:26:26: note: expanded from macro 'MACROB'
#define MACROB(name) B_##name
^
So, it seems the preprocessor is not taking the result of MACROA(object), but it is considering the expression itself so that it tries to make B_MACROA(object). So, what do I have to do to make the preprocessor consider the result of a macro passed to another macro?
The concatenation operator acts weird. It concatenates first and evaluates later:
void *MACROB(MACROA(object)); // The original line
void *B_MACROA(object); // Becomes this, nothing more to expand
You can solve it this way:
#define CONC(a,b) a ## b
#define MACROA(name) CONC(A_, name)
#define MACROB(name) CONC(B_, name)

Resources