Defining C macros in preprocessor if statements - c-preprocessor

Below I change the value of the function that I call depending on the value of INPUT:
#include <stdio.h>
#define INPUT second
#if INPUT == first
#define FUNCTOCALL(X) first(X)
#elif INPUT == second
#define FUNCTOCALL(X) second(X)
#endif
void first(int x) {
printf("first %d\n", x);
}
void second(int x) {
printf("second %d\n", x);
}
int main() {
FUNCTOCALL(3);
return 0;
}
However, the output is first 3, even if INPUT is equal to second, as above. In fact, the first branch is always entered, regardless of the value of INPUT. I'm completely stumped by this - could someone explain what stupid mistake I'm making?

The c preprocessor only works on integer constant expressions in its conditionals.
If you give it tokens it can't expand (such as first or second where first and second aren't macros)
it'll treat them as 0 and 0 == 0 was true last time I used math. That's why the first branch is always taken.
6.10.1p4:
... After all replacements due to macro expansion and the defined
unary operator have been performed, all remaining identifiers
(including those lexically identical to keywords) are replaced with
the pp-number 0, and then each preprocessing token is converted into a
token. ...

You have no macros first and second defined. Be aware that the pre-processor is not aware of C or C++ function names!* In comparisons and calculations (e. g. #if value or #if 2*X == Y), macros not defined (not defined at all or undefined again) or defined without value evaluate to 0. So, as first and second are not defined, INPUT is defined without value, and the comparison in both #if expressions evaluates to 0 == 0...
However, if you did define the two macros as needed, they would collide with the C function names and the pre-processor would replace these with the macro values as you just defined them, most likely resulting in invalid code (e. g. functions named 1 and 2)...
You might try this instead:
#define INPUT SECOND
#define FIRST 1
#define SECOND 2
#if INPUT == FIRST
#define FUNCTOCALL(X) first(X)
#elif INPUT == SECOND
#define FUNCTOCALL(X) second(X)
#else
# error INPUT not defined
#endif
Note the difference in case, making the macro and the function name differ.
* To be more precise, the pre-processor is not aware of any C or C++ tokens, so it does not know about types like int, double, structs or classes, ... – all it knows is what you make it explicitly aware of with #define, everything else is just text it operates on and, if encountering some known text nodes, replacing them with whatever you defined.

Related

Why is the output different in these two scenarios

Please give me full description....
The first snippet of code has the 'function call' (macro invocation) before the increment operator, and second one has the function call after the increment operator.
#include <stdio.h>
#define square(x) x*x
int main()
{
int a,b=3;
a=square (b)++;
printf("%d%d",a,b);
return 0;
}
output:
124
why is 124 returned here
#include <stdio.h>
#define square(x) x*x
int main()
{
int a,b=3;
a=square (b++);
printf("%d%d",a,b);
return 0;
}
output:
125
and 125 here?
The thing to keep in mind is that macros provide simple substitution of preprocessor tokens. In particular, they may evaluate their arguments more than once, and if not guarded by parentheses, they may produce unintended reassociation.
In the first example, we have
a=square (b)++;
This expands to:
a=b*b++;
This is actually undefined behavior, since the b and b++ are unsequenced, and b++ modifies b. In your case, you are seeing 12 and 4 for a and b, so it would seem that the first value of b is picking up the incremented value, so you're getting 4*3, but you can't count on this behavior. The final value of b is 4 since it is incremented once.
In the second example, we have:
a=square (b++);
This expands to:
a=b++*b++;
This is again undefined behavior. In your case, it appears that you're getting 4*3 (or 3*4), but again, you can't count on this behavior. The final value of b is 5 since it is incremented twice, but this too is undefined behavior.
In addition to Tom's answer, which explains what is happening, here is an example of how you could define a macro for squaring a number safely:
#define SQR(x) ( \
{ \
__auto_type x_ = (x); \
\
x_ * x_; \
} \
)
It only has an appearance of x, and therefore it doesn't evaluate it twice. The copy x_ is used instead. Note that variables created in a macro may conflict with other variables created in the function that calls the macro. To avoid name collisions you use special names that shouldn't be used in normal code such as a trailing _.
With this macro, this:
a = SQR(b++);
will be equivalent to this:
a = SQR(b);
b++;
Warning: This works on some compilers as an extension (GCC for example), but it is not standard C.
Another option, if you want standard C, is to use an inline function. It is ok if you want it to work on just one type (there is _Generic in C11, but I never used it, so no idea).

Argument counting in macro

I'm trying to understand the argument counting in C preprocessing macro and the idea in this answer. We have the following macro (I changed the number of arguments for simplicity):
#define HAS_ARGS(...) HAS_ARGS_(__VA_ARGS__, 1, 1, 0,)
#define HAS_ARGS_(a, b, c, N, ...) N
As far as I understand the purpose of this macro is to check if the given varargs empty. So on empty varargs the macro invokation is replaced with 0 which seems fine. But with a single argument it also turns into 0 which I seems strange.
HAS_ARGS(); //0
HAS_ARGS(123); //also 0
HAS_ARGS(1, 2); //1
LIVE DEMO
I think I understand the reason. In case of empty varargs a is replaced with empty preprocessing token, in case of a single argument vararg a is replaced with the argument yielding the same result.
Is there a way to get 0 returned in case varargs are empty, 1 in case argument number is from 1 to the defined in HAS_ARGS_ macro invokation without using comma-swallowing or other non-conforming tricks. I mean
SOME_MACRO_F() //0
SOME_MACRO_F(234) //1
SOME_MACRO_F(123, 132) //1
//etc
You cannot pass zero arguments to HAS_ARGS(...). ISO C (and C++, at least for the next two years) requires that an ellipsis corresponds to at least one additional argument after the last named one.
If there are no named ones, then the macro needs to be passed at least one argument. In the case of HAS_ARGS() the extra argument is simply an empty token sequence. Zero arguments is simply not possible.
This is exactly the use case in the answer. The target macro expects at least one argument. So we can use a wrapper accepting only an ellipsis for "overload resolution". A better name probably would have been HAS_MORE_THAN_1_ARGS. Because that's what the predicate is meant to tell you. Alas, I favored brevity on that answer.
It seems difficult to compute that at compile-time, but you can do it at run-time by stringifying the arguments and testing if the string is empty.
Tested with gcc:
#include <stdio.h>
#define HAS_ARGS(...) (#__VA_ARGS__[0] != '\0')
int main()
{
printf("%d %d %d %d\n",HAS_ARGS(),HAS_ARGS(10),HAS_ARGS(20,"foo"),HAS_ARGS(10,20));
return 0;
}
this prints:
0 1 1 1
behind the scenes, here's what the pre-processor outputs:
int main()
{
printf("%d %d %d %d\n",(("")[0] != '\0'),(("10")[0] != '\0'),(("20,\"foo\"")[
0] != '\0'),(("10,20")[0] != '\0'));
return 0;
}

C macros using enum

I am trying to use #if macros by defining the type of operation to invoke the right code, So i made a very simple example similar to what I am trying to do:
#include <stdio.h>
enum{ADD,SUB,MUL};
#define operation ADD
int main()
{
int a = 4;
int b = 2;
int c;
#if (operation == ADD)
c = a+b;
#endif
#if (operation == SUB)
c = a-b;
#endif
#if (operation == MUL)
c = a*b;
#endif
printf("result = %i",c);
return 0;
}
But unfortunately that does not work I get the following result = 8... if I replace The operation with numbers it works fine .... But i want it to work as it is described above.
Any help
The preprocessor is a step that is (in a way) done before the actual compiler sees the code. Therefore it has no idea about enumerations or their values, as they are set during compilation which happens after preprocessing.
You simply can't use preprocessor conditional compilation using enumerations.
The preprocessor will always consider that as false:
#if IDENT == IDENT
It can only test for numeric values.
Simplify your code and feed it to the preprocessor:
enum {ADD,SUB,MUL};
#define operation ADD
int main()
{
(operation == ADD);
}
The result of the preprocessor output is:
enum {ADD,SUB,MUL};
int main()
{
(ADD == ADD);
}
As you see, the enumerate value hasn't been evaluated. In the #if statement, that expression is just seen as false.
So a workaround would be to replace your enumerate by a series of #define:
#define ADD 1
#define SUB 2
#define MUL 3
like this it works. Output of preprocessor output is now:
int main()
{
int a = 4;
int b = 2;
int c;
c = a+b;
# 28 "test.c"
printf("result = %i",c);
return 0;
}
the solution is:
either rely at 100% on the preprocessor (as the solution above suggests)
or rely at 100% on the compiler (use enums and real if statements)
As others have said, the preprocessor performs its transformations at a very early phase in compilation, before enum values are known. So you can't do this test in #if.
However, you can just use an ordinary if statement. Any decent compiler with optimization enabled will detect that you're comparing constants, perform the tests at compile time, and throw out the code that will never be executed. So you'll get the same result that you were trying to achieve with #if.
But i want it to work as it is described above.
You seem to mean that you want the preprocessor to recognize the enum constants as such, and to evaluate the == expressions in that light. I'm afraid you're out of luck.
The preprocessor knows nothing about enums. It operates on a mostly-raw stream of tokens and whitespace. When it evaluates a directive such as
#if (operation == SUB)
it first performs macro expansion to produce
#if (ADD == SUB)
. Then it must somehow convert the tokens ADD and SUB to numbers, but, again, it knows nothing about enums or the C significance of the preceding code. Its rule for interpreting such symbols as numbers is simple: it replaces each with 0. The result is that all three preprocessor conditionals in your code will always evaluate to true.
If you want the preprocessor to do this then you need to define the symbols to the preprocessor. Since you're not otherwise using the enum, you might as well just replace it altogether with
#define ADD 1
#define SUB 2
#define MUL 3
If you want the enum, too, then just use different symbols with the preprocessor than you use for the enum constants. You can use the same or different values, as you like, because never the twain shall meet.
Another solution would be to have the enum in an included header file.

C - Macro contradiction

I just started learning C and I am not sure about how everything works. Some of examples simply looks weird to me and I cannot predict what would it print. I am programming in GCC, I mean it is my compiler, so every code I test is in GCC.
I understood pointers etc how that all stuff work, but also as you know there are macros. Macros are very weird, and I discovered one example I have no explanation about. For example look at this code particular code:
#include <stdio.h>
int main(void){
#define A 1
if(A == 0){
#define B 1
}
#ifdef B
printf("B is defined, which means that A == 0.\n");
#elif
printf("B isn't defined, which means that A == 1.\n");
#endif
printf("Value of A is %d\n", A);
return 0;
}
What should it print? Well, I though it is easy to guess, but now I see that it is not very easy. The result is not what i thought is.
This was my reasoning: we firstly define A to be 1 and then if A is 0 then define B to be 1. So, if B is defined it means that A == 0 and otherwise A == 1. But, surprisingly it prints:
B is defined, which means that A == 0.
Value of A is 1
What? It just printed a contradiction. I am not sure if this is some weird thing in GCC (because I have no visual studio or other compiler to test it). However, I am 99% sure I somehow misunderstood macros. I tried using variables instead of macros and it works properly.
Is it an issue, or did I simply misunderstand how macros work? Please keep in mind that I'm C beginner, so take it easy :).
Thank you in advance.
Macros are part of the preprocessor before the code is actually compiled. The compiler will search the code for all preprocessor directives and modify the code accordingly. So when the compiler gets to if(A == 0) {#define B 1} it has already been expanded to if(0 == 1) { }.
Macros makes it easy to configure an aspect of your code or to replace magic numbers into meaningful defines. For example:
#define DO_HOUR_CALCULATION
#define NUMBER_OF_SECONDS_PER_MINUTE (60)
#define NUMBER_OF_SECONDS_PER_HOUR (NUMBER_OF_SECONDS_PER_MINUTE * 60)
...
#ifdef DO_HOUR_CALCULATION
int hours = time / NUMBER_OF_SECONDS_PER_HOUR;
int minutes = (time % NUMBER_OF_SECONDS_PER_HOUR) / NUMBER_OF_SECONDS_PER_MINUTE;
#endif // defined(DO_TIME_CALCULATION)
Another use is to simplify a repeated or configurable task:
#define DEBUG
#ifdef DEBUG
#define DPRINTF(fmt, args...) printf(fmt, ## args)
#else
#define DPRINTF(args...) do {} while (0)
#endif
...
ret = read(fd, p_buffer, buf_size);
DPRINTF("read(fd) returned %d\n", ret);
Hope this helps you and happy coding!
Preprocessing directives are processed before non-preprocessing tokens are translated. And particularly, preprocessing directives are always evaluated at compile time, and never at runtime (cf. C standard, e.g. this draft).
If a token is a preprocessing token is defined as follows (all others are non-preprocessing tokens):
6.10 Preprocessing directives
(2) A preprocessing directive consists of a sequence of preprocessing
tokens that begins with a # preprocessing token that (at the start of
translation phase 4) is either the first character in the source file
(optionally after white space containing no new-line characters) or
that follows white space containing at least one new-line character
So if(A == 0) are non-preprocessing tokens (as the respective line does not start with a #, optionally with some space characters before), while #define B 1 is a preprocessing token.
According to the translation phases, preprocessing tokens are evaluated at translation time before the other tokens:
5.1.1.2 Translation phases
(4) Preprocessing directives are executed, macro invocations are
expanded, and _Pragma unary operator expressions are executed.
(7) ... The resulting tokens are syntactically and semantically
analyzed and translated as a translation unit.
So B will be defined already before if(A==0) will be translated, and particularly before if(A==0) will be executed. Thus, B will always be defined in your program.
The #define B 1 does not occur at run time. It happens at compile time. So #define B 1 is part of the compilation regardless of the result of A == 0, a run-time comparison
if(A == 0){
#define B 1
}
The following code
#ifdef B
printf("B is defined, which means that A == 0.\n");
#elif
printf("B isn't defined, which means that A == 1.\n");
#endif
is then the same as
printf("B is defined, which means that A == 0.\n");

Can I capture the underlying value of one macro when defining another?

Imagine I want to #define a macro such that it is equal to the current value of another macro (if such a concept exists).
For example:
#include "def_a.h" // defines macro A
#define B A
This defines B to be A. If A later changes definition (i.e., through a redefinition) the value of B also changes (because B expands to A at the point of use, which further expands to the new value of A).
What I'd like is some way to "bake in" the value of A into B so that B just expands to the value of A, not A itself.
For example:
#define A first
#define B BAKE_IN(A)
#undef A
#define A second
#define C BAKE_IN(A)
#undef A
#define A third
// here I want B to expand to first, and C to expand to second
Of course BAKE_IN is not a real thing, but I'm wondering if there is some way to achieve this effect.
Now, I didn't really say what should happen if A itself is defined in terms of other macros, but I'm OK both with "one level of expansion" (i.e., B gets the value of A is expanded, so further macros remain) and also "full expansion" (i.e., A is fully expanded, recursively, as it would be at a point of use).
Macros are never replaced in the body of a #define directive, so there is no way to define a macro as the current value of another macro, except for the limited case of macros whose value is a constant arithmetic expression.
In the latter case, you can use BOOST_PP_ASSIGN_SLOT from the Boost preprocessor library. (Although most of the Boost libraries are C++-specific, the Boost preprocessor library works for both C and C++, and has no dependency on any other Boost component.)
I don't think there is a clean solution. The closest thing that I found is to preserve "stringified" values within char arrays:
#include <stdio.h>
#define BAKE_IN(X, id) BAKE_IN_REAL(X ## _, X, id)
#define BAKE_IN_REAL(X, Y, id) static const char X ## id[] = #Y;
#define BAKE_OUT(X, id) X ## _ ## id
#define A first
BAKE_IN(A, 1)
#define B BAKE_OUT(A, 1)
#undef A
#define A second
BAKE_IN(A, 2)
#define C BAKE_OUT(A, 2)
#undef A
int main(void)
{
printf("%s\n", B); // prints "first"
printf("%s\n", C); // prints "second"
return 0;
}
The idea is that BAKE_IN macro declares object named as e.g. A_1, which holds the current expansion of A.
There are two major limitations:
Every pair of BAKE_IN and BAKE_OUT needs unique id
The expansion is only available in "stringified" form

Resources