Function of '+' in #if defined? - c

#include <stdio.h>
#define MIN 0
#if defined(MIN) + defined(MAX)
#define MAX 10
#endif
int main()
{
printf("%d %d\n", MAX, MIN);
return 0;
}
Output
10 0
What is the meaning of #if defined(MIN) + defined(MAX)?
Why it is working when #define MAX 10 is defined later?

The defined operator evaluates to 0 or 1 depending on whether the symbol is defined.
Arithmetic works in preprocessor expressions, and 1 + 0 is 1 so the #if is taken.

In this case, it is the same as ||:
#if defined(MIN) || defined(MAX)
...
#endif
The defined(...) operator produces a 0 or 1 integer, and #if takes any integer expression, as long as it can be evaluated at the time of preprocessing.
Using + in preprocessor conditions lets you build more interesting constructs, for example
#if (defined(MIN) + defined(MAX) + defined(AVG)) >= 2
...
#endif
This means "at least two of the three items, {MIN, MAX, AVG} are defined".

You are allowed to do simple math in the preprocessor. #if defined(...) evaluates to an integer zero or one. defined(MIN) is 1, while defined(MAX) is 0, so the whole expression evaluates to 1 = true, and MAX gets defined.

Related

how macro works different with integers and char in my C-code

I'am familiar with the conditional compilation with macros in "C" language but some piece of code makes me confused ,I can understand how CODE-1 works, nothing is assigned into X therefore Y is defined as 5 (else condition) and on print Y we will get 5 as a output.
but in the CODE-2 which is quite similar to the CODE-1 except the
"#if X == A" condition which gives the output as 3,which i don't understand how it can produce output as 3 .Can anyone tells me how
"#if X == 3"
and
"#if X == A"`
makes the difference in the output.
CODE-1
#include <stdio.h>
#if X == 3
#define Y 3
#else
#define Y 5
#endif
int main()
{
printf("%d", Y);
return 0;
}
//output : 5
CODE-2
#include <stdio.h>
#if X == A
#define Y 3
#else
#define Y 5
#endif
int main()
{
printf("%d", Y);
return 0;
}
//output : 3
I expect the output of CODE-2 to be 5, but the actual output is 3.
Tokens in macro conditionals that aren't further expandable to integers (aren't macros) get replaced by 0.
6.10.1p4:
Prior to evaluation, macro invocations in the list of preprocessing
tokens that will become the controlling constant expression are
replaced (except for those macro names modified by the defined unary
operator), just as in normal text. If the token defined is generated
as a result of this replacement process or use of the defined unary
operator does not match one of the two specified forms prior to macro
replacement, the behavior is undefined. 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. The resulting tokens
compose the controlling constant expression which is evaluated
according to the rules of 6.6.
Since neither X nor why Y is defined in your second snippet, it becomes equivalent to:
#if 0 == 0
#define Y 3
#else
#define Y 5
#endif
which naturally resolves to the first branch.

Detecting if a macro argument is a typename

Within C11/gnuC11 is it possible to write a macro that returns an integer constant expression of value 1 or 0 respectively if the macro argument is or isn't a type name or at least a macro can distinguish between integer constant expressions and typenames (i.e., if can detect the argument isn't one of these, it can assume it is the other)?
#define IS_TYPENAME(X) /*???*/
_Static_assert( IS_TYPENAME(int), "" );
_Static_assert( !IS_TYPENAME(42), "" );
Motivation:
My motivation was to wrap _Alignas with a macro that would simply do nothing if the suggested alignment (either type or integer expression) was less than the current one (normal _Alignas with a smaller alignment results in an error) and so I wanted to also accept either a typename or an integer expr, but now I'm thinking simply requiring an integer expr (which you can always get from a typename by applying _Alignof) will be the simpler/clearer way to go.
In order to do this, you will need to check if the parameter is of type integer, and you need to check if it is a type or an expression.
Checking if a macro parameter, that may be a type or an expression, is of integer type:
This can be done with _Generic. A _Generic expression cannot contain two types that are identical, so it should suffice if you compare against all the stdint.h types only. Since these will alias with the default integer types, but not collide with each other (like for example int and long might).
Now _Generic doesn't accept a type as operand, so you have to tweak the input to always become an expression.
The trick that I invented just now, is to use the ambiguity between the parenthesis operator and the cast operator, and at the same time use the ambiguity between unary + and binary + operators.
Given (x)+0.
If x is a type, () becomes the cast operator and +0 is the unary addition operator applied to an integer constant.
If x is an expression, it will get parenthesized and then + is the binary addition operator.
So you can do:
#define IS_INT(x) _Generic((x)+0, \
uint8_t: 1, int8_t: 1, \
uint16_t: 1, int16_t: 1, \
uint32_t: 1, int32_t: 1, \
uint64_t: 1, int64_t: 1, \
default: 0)
This will work for all integer, character and float types, as well as pointers. It will not work on struct/union types (compiler error). It will not work with void* and probably not with NULL (compiler error, can't do pointer arithmetic).
Checking if a macro parameter, that may be a type or an expression, is an expression:
This can also be done using the same trick as above, use the ambiguity between different operators. For example:
#define IS_EXPR(x) (!!(x) + !(x) + 1 == 2)
If x is a non-zero integer constant expression, we get 1 + 0 + 1 = 2.
If x is a zero integer constant expression, we get 0 + 1 + 1 = 2.
If x is a type, we get !!(int)+!(int)+1 which equals 0. Both + are unary.
This doesn't make a difference between float and integers though, so we need to combine this trick with the IS_INT macro.
Solution:
#define IS_INTCONSTEXPR(x) ( IS_INT(x) && IS_EXPR(x) )
Complete example with test cases, printing 1 if integer constant expression, otherwise 0:
#include <stdint.h>
#include <stdio.h>
#define IS_INT(x) _Generic((x)+0, \
uint8_t: 1, int8_t: 1, \
uint16_t: 1, int16_t: 1, \
uint32_t: 1, int32_t: 1, \
uint64_t: 1, int64_t: 1, \
default: 0)
#define IS_EXPR(x) (!!(x) + !(x) + 1 == 2)
#define IS_INTCONSTEXPR(x) ( IS_INT(x) && IS_EXPR(x) )
#define test(arg) printf("%d %s\n", IS_INTCONSTEXPR(arg),(#arg))
int main (void)
{
test(42);
test(sizeof(int));
test(1+1);
test(int);
test(unsigned int);
test(42.0);
test(double);
test(uint32_t);
test(uint32_t*);
test(_Bool);
_Static_assert( !IS_INTCONSTEXPR(int), "" ); // OK, passed
_Static_assert( IS_INTCONSTEXPR(42), "" ); // OK, passed
return 0;
}
Output:
1 42
1 sizeof(int)
1 1+1
0 int
0 unsigned int
0 42.0
0 double
0 uint32_t
0 uint32_t*
0 _Bool

Can #define process arithmetic operations in preprocessing?

Can the C macro #define process arithmetic operations in preprocessing?
For example, if I write
#define A 1 + 1
will it be pre-processed to be equivalent to
#define A 2
before compiling?
Furthermore, is it possible to define constants this way without computation overhead:
#define A 1
#define B A + 1
#define C B + 1
...
?
Macros are text replacements (token replacements to be more accurate).
#define A 1 + 1
int main() { printf("%d\n", A); }
will expand to (run gcc -E on the source to get the preprocessor expansion)
int main() { printf("%d\n", 1 + 1); }
(which BTW, is why it's wise to heavily parenthesize in macros (#define A (1+1)), because
you'll usually want A*3 to then be 6 ( (1+1)*3 ) not 4 ( 1+1*3) ) ).
And yes 1+1, seeing as it satisfies the standard's rules for integer constant expressions, is pretty much guaranteed to be processed at compile time and so you can use it in contexts where an integer constant expression is required.
E.g.:
#define A (1+1)
extern char array[A] = { [A-1]='c' } ; //ICE required
struct s { int bitfield:A; }; //ICE required
enum { a = A }; //ICE required
int x = A; //ICE required
int main ()
{
switch(1) case A: puts("unreachable"); //ICE required
}

Incorrect multiplication of integers in C

A C-coded S-function in Simulink was showing incorrect behaviour and I have managed to narrow down the problem to an incorrect multiplication of integers.
At the start of the code, I have something like:
#define NRBF 21
#define NRBF1 NRBF+1
Then, in a function in the script I have:
void function_name(SimStruct *S, const int_T a)
{
...
int_T base;
base = a*NRBF1;
printf("%i\t", a);
printf("%i\t", NRBF1);
printf("%i\n", base);
..
}
Now, if a=0, NRBF=21, I have (instead of base=0)
0 22 1
If a=1, NRBF=21, I have (as expected base=22)
1 22 22
If a=2, NRBF=21, I have (instead of base=44)
2 22 43
Now, I must say I am a bit baffled. I tried to change the line of the multiplication to
base = a* (int_T)NRBF1;
but it does not solve the problem.
Any help would be greatly appreciated! Thank you!
The problem is here:
You define your macros like this:
#define NRBF 21
#define NRBF1 NRBF+1
When you write this:
base = a*NRBF1;
The preprocessor replaces NRBF1 textually with 21+1 which results in this:
base = a*21+1;
but you intended this:
base = a*(21+1);
Therefore you need to define your macro like this:
#define NRBF1 (NRBF+1)
With the macro expanded, the line looks like:
base = a*NRBF+1;
For a equal to 0, the expression is 0 * 21 + 1 which is 1.
For a equal to 2, the expression is 2 * 21 + 1 which is 43.
The solution is to put parentheses in the macro definition:
#define NRBF1 (NRBF + 1)
This is a good rule for any macro with an expression as its right-hand side.
Remember that macros are just text-substituted into the code.
It's basically calculating alright
0*21+1 = 1
The macro is expanded but the * has precedence over +. That's why this happens.
A more detail explanation would be
#define NRBF 21
#define NRBF1 NRBF+1
So what is going on
base = a*NRBF1;
or
base = a*NRBF+1
Now when a = 0 then base = 1
when a = 1 then base = 21+1 ...so on.
Correct way would be to wrap it aropund parentheses.
#define NRBF1 (NRBF+1)
Some more pitfalls:
That when you add a macro like this #define SQR(X) X*X
For some example like this where same precedence operators are there next to next then it will be problematic.
int i = 100/SQR(10);
Then it will be expanded to
int i = 100/10*10
Now same precedence operators are here executed left to right.
So it will result in i=100.
Solution same #define SQR(X) (X*X)
Also when passing an expression like this SQR(i+1) then it will be expanded to i+1*i+1=2*i+1. So a bit more correct would be
#define SQR(X) ((X)*(X))
Even with that you wouldn't be able to avoid few things if you forget one thing macro just expands - it does nothing more.
You can't use macro like this
SQR(i++) which will be expanded to ((i++)*(i++)). So you are increasing the i twice which is what you didn't mean. Moreover this will result in undefined behavior.
the define doesn't create a single value 22 but the expression 21 + 1. I wonder whether your problems go away if you change your second #define to
#define NBRF1 (NBRF + 1)

Can the C preprocessor perform integer arithmetic?

As the questions says, is the C preprocessor able to do it?
E.g.:
#define PI 3.1416
#define OP PI/100
#define OP2 PI%100
Is there any way OP and/or OP2 get calculated in the preprocessing phase?
Integer arithmetic? Run the following program to find out:
#include "stdio.h"
int main() {
#if 1 + 1 == 2
printf("1+1==2\n");
#endif
#if 1 + 1 == 3
printf("1+1==3\n");
#endif
}
Answer is "yes", there is a way to make the preprocessor perform integer arithmetic, which is to use it in a preprocessor condition.
Note however that your examples are not integer arithmetic. I just checked, and gcc's preprocessor fails if you try to make it do float comparisons. I haven't checked whether the standard ever allows floating point arithmetic in the preprocessor.
Regular macro expansion does not evaluate integer expressions, it leaves it to the compiler, as can be seen by preprocessing (-E in gcc) the following:
#define ONEPLUSONE (1 + 1)
#if ONEPLUSONE == 2
int i = ONEPLUSONE;
#endif
Result is int i = (1 + 1); (plus probably some stuff to indicate source file names and line numbers and such).
The code you wrote doesn't actually make the preprocessor do any calculation. A #define does simple text replacement, so with this defined:
#define PI 3.1416
#define OP PI/100
This code:
if (OP == x) { ... }
becomes
if (3.1416/100 == x) { ... }
and then it gets compiled. The compiler in turn may choose to take such an expression and calculate it at compile time and produce a code equivalent to this:
if (0.031416 == x) { ... }
But this is the compiler, not the preprocessor.
To answer your question, yes, the preprocessor CAN do some arithmetic. This can be seen when you write something like this:
#if (3.141/100 == 20)
printf("yo");
#elif (3+3 == 6)
printf("hey");
#endif
YES, I mean: it can do arithmetic :)
As demonstrated in 99 bottles of beer.
Yes, it can be done with the Boost Preprocessor. And it is compatible with pure C so you can use it in C programs with C only compilations. Your code involves floating point numbers though, so I think that needs to be done indirectly.
#include <boost/preprocessor/arithmetic/div.hpp>
BOOST_PP_DIV(11, 5) // expands to 2
#define KB 1024
#define HKB BOOST_PP_DIV(A,2)
#define REM(A,B) BOOST_PP_SUB(A, BOOST_PP_MUL(B, BOOST_PP_DIV(A,B)))
#define RKB REM(KB,2)
int div = HKB;
int rem = RKB;
This preprocesses to (check with gcc -S)
int div = 512;
int rem = 0;
Thanks to this thread.
Yes.
I can't believe that no one has yet linked to a certain obfuscated C contest winner. The guy implemented an ALU in the preprocessor via recursive includes. Here is the implementation, and here is something of an explanation.
Now, that said, you don't want to do what that guy did. It's fun and all, but look at the compile times in his hint file (not to mention the fact that the resulting code is unmaintainable). More commonly, people use the pre-processor strictly for text replacement, and evaluation of constant integer arithmetic happens either at compile time or run time.
As others noted however, you can do some arithmetic in #if statements.
Be carefull when doing arithmetic: add parenthesis.
#define SIZE4 4
#define SIZE8 8
#define TOTALSIZE SIZE4 + SIZE8
If you ever use something like:
unsigned int i = TOTALSIZE/4;
and expect i to be 3, you would get 4 + 2 = 6 instead.
Add parenthesis:
#define TOTALSIZE (SIZE4 + SIZE8)

Resources