C preprocessors and order of operations - c++

I'm learning C, but I do not understand this:
#define square(x) x*x
a = square(2+3) //a = 11
When this is run, why does a end up being 11?

It expands to 2+3*2+3, which is equivalent to 2+(3*2)+3. Use parentheses to fix it:
#define square(x) ((x)*(x))
Now try it with square(x++) and you'll run into more problems (undefined behavior). Avoid doing this as a macro if you can.

square(2+3) expands to 2+3*2+3 which is equivalent to 2+(3*2)+3 [* has higher precedence than +]
On gcc you can use -E option to see what your preprocessor generates
C:\Users\SUPER USER>type a.c
#define square(x) x*x
int main()
{
a = square(2+3); //a = 11
}
C:\Users\SUPER USER>gcc -E a.c
# 1 "a.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "a.c"
int main()
{
a = 2+3*2+3;
}
Remedy
Try this
#define square(x) ((x)*(x))

Try:
#define square(x) ((x)*(x))

Because 2 + 3 is substituted literally in the expression x * x, it becomes 2 + 3 * 2 + 3, and the * operator has a higher precedence so you don't get the expected result.
Always enclose macro arguments and the whole expression in parentheses to avoid this:
#define SQUARE(x) ((x) * (x))
Also note that any expression you pass will be evaluated twice, and that can be undesired if the expression has a side effect such as an assignment, or a function call. In these cases it is better to use an inline function.

think about what you get when the macro is expanded. The c preprocessor will expand this as
a = 2 + 3 * 2 + 3
You need to correctly define your macro. Always enclose the macro variable in parenthesis. This would give you the expected result.
#define square(x) ((x)*(x))
The macro expansion would be this:
a = ((2 + 3) * (2 + 3))

Related

Boost.Preprocessor index list with macro

I am trying to use Boost.Preprocessor to do some compile-time work. I want to index a table using values that are computed in other macros. When I try I get the following error: "concatenation with '(' in macro 'BOOST_PP_BOOL_I' does not create a valid token."
This is the simplest code that produces the issue.
#define MY_TABLE (0, (1, BOOST_PP_NIL))
#define MY_INDEX_FUNCTION(x) (x)
void func() {
int y = BOOST_PP_LIST_AT(MY_TABLE, MY_INDEX_FUNCTION(0));
}
It is pretty easy to determine that removing the parens in MY_INDEX_FUNCTION resolves the issue in this case. My actual code uses a much more complex function to calculate the table index in a much larger table.
Is there something that I can do or change that would fix this such that the parens and more complex macros don't cause problems?
The second parameter of BOOST_PP_LIST_AT takes an index/integer. It works with tricky preprocessor hacks under the hood. The parameter(expanded) should be exactly an integer-literal, not an integer inside parenthesis. The MY_INDEX_FUNCTION should be changed, so that the parameter passed to the BOOST_PP_LIST_AT is literally an integer-literal:
#define MY_INDEX_FUNCTION(x) x
The macro does not work with arithmetic expressions, this will not work:
#define MY_INDEX_FUNCTION(x) (x+1)
NOR
#define MY_INDEX_FUNCTION(x) x+1
But you can do this with
#define MY_INDEX_FUNCTION(x) MY_INDEX_FUNCTION_ ## x
#define MY_INDEX_FUNCTION_0 1
#define MY_INDEX_FUNCTION_1 2
#define MY_INDEX_FUNCTION_2 3
//...
This macro definitions can be created by a (python-)script
def my_index_function(x):
# insert the behavior of the macro here
return x+1
MACRO_NAME = "MY_INDEX_FUNCTION"
INDEX_MAX = 255
for x in range(INDEX_MAX):
print("#define %s_%i %i" % (
MACRO_NAME,
x,
my_index_function(x),
))
print("#define %s(x) %s_ ## x" % (
MACRO_NAME,
MACRO_NAME,
))

extra indirection in C preprocessor stringification making difference

#define N 1
#define A(N) #N
#define S_A A(N)
#define B_(N) #N
#define B(N) B_(N)
#define S_B B(N)
#include <stdio.h>
int main(void) {
puts(S_A);
puts(S_B);
}
outputs N and 1 instead of two 1s.
Why is the extra indirection making a difference?
It works different because the macro expansion of N only happens on the "use" of N. So S_A exands to A(N), which is expanded to #N. In S_B it is expanded to B(N), which is expanded to _B(1), and then #1. Why? Well, how would you do something like:
#define COMBINE(A, B) A##B
#define foo 1
#define bar 2
int COMBINE(foo, bar) = 34;
so that it generates int foobar = 34;, and not the illegal int 12 = 34;.
Did you intend to use a ## operator for token pasting?
puts(S_A); //Gets expanded into puts(A(N)) --> puts(#N)
and
puts(S_B); //Gets expanded into puts(B(N)) --> puts(_B(1)) --> puts(#1)
Without affecting your macros much, if you intend to print 1,1 both the times, you could Use the macros this way:
#define N "1" //instead of 1
#define A(N) N //instead of #N
#define B_(N) N //instead of #N

Macro output explanation

Can someone explain the output of this program -
#include<stdio.h>
#include<conio.h>
#define FUDGE(k) k+3.14159
#define PR(a) printf(#a" = %d\t ",(int)(a))
#define PRINT(a) PR(a);putchar('\n')
int main()
{
int x=2;
PRINT(x*FUDGE(2));
printf(\n);
PR(x*FUDGE(2));
return 0;
}
OUTPUT -
x*2+3.14159 = 7
x*FUDGE(2) = 7
Why is FUDGE(2) getting printed in second and not in the first statement.
The # operator is strange. It works before expanding the parameter.
So when calling PR(x*FUDGE(2)), # is applied to x*FUDGE(2) before FUDGE is expanded.
However, in PRINT(x*FUDGE(2)), FUDGE is expanded before passing it on to PR. When PR applies # to it, it has already been expanded.
Because in the first you use PRINT which expands the argument when it "calls" PR.

Error: macro names must be identifiers using #ifdef 0

I have the source code of an application written in C++ and I just want to comment something using:
#ifdef 0
...
#endif
And I get this error
error: macro names must be identifiers
Why is this happening?
The #ifdef directive is used to check if a preprocessor symbol is defined. The standard (C11 6.4.2 Identifiers) mandates that identifiers must not start with a digit:
identifier:
identifier-nondigit
identifier identifier-nondigit
identifier digit
identifier-nondigit:
nondigit
universal-character-name
other implementation-defined characters>
nondigit: one of
_ a b c d e f g h i j k l m
n o p q r s t u v w x y z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z
digit: one of
0 1 2 3 4 5 6 7 8 9
The correct form for using the pre-processor to block out code is:
#if 0
: : :
#endif
You can also use:
#ifdef NO_CHANCE_THAT_THIS_SYMBOL_WILL_EVER_EXIST
: : :
#endif
but you need to be confident that the symbols will not be inadvertently set by code other than your own. In other words, don't use something like NOTUSED or DONOTCOMPILE which others may also use. To be safe, the #if option should be preferred.
Use the following to evaluate an expression (constant 0 evaluates to false).
#if 0
...
#endif
This error can also occur if you are not following the marco rules
Like
#define 1K 1024 // Macro rules must be identifiers error occurs
Reason: Macro Should begin with a letter, not a number
Change to
#define ONE_KILOBYTE 1024 // This resolves
#ifdef 0
...
#endif
#ifdef expect a macro rather than expression
when using constant or expression
#if 0
...
#endif
or
#if !defined(PP_CHECK) || defined(PP_CHECK_OTHER)
..
#endif
if #ifdef is used the it reports this error
#ifdef !defined(PP_CHECK) || defined(PP_CHECK_OTHER)
..
#endif
Where #ifdef expect a macro rather than macro expresssion
Note that you can also hit this error if you accidentally type:
#define <stdio.h>
...instead of...
#include <stdio.>

C++ anonymous variables

Why won't this work?
0. #define CONCAT(x, y) x ## y
1.
2. #define VAR_LINE(x) \
3. int CONCAT(_anonymous, __LINE__) = x
4.
5. #define VAR_LINE2(x) \
6. int _anonymous ## x = 1
7.
8. int main()
9. {
10. VAR_LINE(1);
11. VAR_LINE(1);
12. VAR_LINE(1);
13. VAR_LINE2(__LINE__);
14. }
The result from the above macro expansion
int _anonymous__LINE__ = 1;
int _anonymous__LINE__ = 1;
int _anonymous__LINE__ = 1;
int _anonymous13 = 1;
It would be convenient if I didn't have to write that __LINE__ macro as an argument.
I'm thinking the problem is pretty clear. I want to be able to generate anonymous variables so that this macro doesn't fail with redefinition error when declaring several variables within the same scope. My idea was to use the predefined __LINE__ macro because no variable will ever be declared on the same line like this. But the macro expansion troubles me, can you help?
Update: Correct answer
Thanks to Luc Touraille. However, there was a tiny problem with the suggested solution. There has to be whitespace between the operands and the ## operator (apparently the standard says otherwise but the the PS3 flavoured GCC would not expand the macro properly if there were no whitespace between the operator and operands).
#define _CONCAT(x,y) x ## y
#define CONCAT(x,y) _CONCAT(x,y)
The VAR_LINE macro now yields:
int _anonymous10 = 1;
int _anonymous11 = 1;
int _anonymous12 = 1;
This has been verified to work under Win32 (Visual Studio 2008), XBOX360 (Xenon) and PS3.
You need to add a level of indirection so that __LINE__ will be expanded:
#define _CONCAT_(x,y) x ## y
#define CONCAT(x,y) _CONCAT_(x,y)
#define VAR_LINE(x) int CONCAT(_anonymous, __LINE__) = x