Will bitshift and arithmetic operations be evaluated by the precompiler? - c++

If I define the following in a C++98 program:
#define BITS_PER_FOO 2
#define BITS_PER_BAR 3
#define FOOBARS (1<<(BITS_PER_FOO*BITS_PER_BAR))
then will FOOBARS get evaluated as 64 by the precompiler? Or will a multiplication and bit-shift operation take place at each location that I use FOOBARS in the code?

No, since it's not the preprocessor's business. It does the usual replace thing, not constant folding.
However, any reasonable compiler will do constant folding, so you should not expect this to correspond to instructions being executed at runtime.

The precompiler just does text substitution - it's essentially copy & paste on steroids. This means that the expression you wrote for FOOBAR will be expanded in full at each replacement location.
Now, any decent compiler will evaluate that whole subexpression at compile time anyway. However, you can save it some work (and have some extra advantages, like having a clear type of your expression, clearer diagnostic, less surprises deriving from substitutions in the wrong places, and having an actual lvalue for your constants instead of expressions) by defining these values as actual constants, like:
const int bits_per_foo = 2;
const int bits_per_bar = 3;
const int foobars = 1<<(bits_per_foo*bits_per_bar);

A multiplication and bit-shift operation will take place at each location that you use FOOBARS.
See: #define Directive (C/C++)
#define forms a macro, meaning the identifier is replaced with everything in the token-string. In your case, the preprocessor replaces instances of FOOBARS with the expression (1<<(BITS_PER_FOO*BITS_PER_BAR))

Related

Macro with run time argument-change giving wrong ans in cpp [duplicate]

When is it is necessary to put the whole (right) expression of a define macro in parenthesis?
If I do something like
#define SUM(x, y) ((x)+(y))
I have to put the right expression into parenthesis, because "+" has a low precedence in C (and it wouldn't work if I would use it in the following context SUM(x, y) * 5U)
Are these parenthesis still required if I use an operator of the highest precedence e.g.
#define F foo()
or even
#define ACCESS(x, y) (x)->(y)
Does an expression exist that that would break the actual meaning as it would do for the SUM() example?)
For the precedence rules I used http://en.cppreference.com/w/c/language/operator_precedence
It's a good practice to use parenthesis to avoid some big blunders. Currently you might think that your operator is having high precedence but suppose you're making the header file of your code and give it to your friend who uses macro from that file with the function having even higher precedence so at that time it will be a great pain to debug the code. You can save this time as a programmer by putting parenthesis.
Some programmers using simple #defines will write
#define ZERO (0)
which is of no use other than complicating things.
Actually the macro is wysiwyg so with that in mind you can decide what parentheses are needed:
SUM(3,4) => ((3)+(4)) // parentheses around 3 and 4 are not necessary
RATIO(3+4,4+5) => ((3+4)/(4+5)) // probably necessary here due to operator precedence
Its not rocket science to figure this out, it's actually quite straightforward.

How to expand & stringify such macro?

I'm making a wrapper for the string parser, which converts string to primitive types. I'm writing unit tests for it, so I need the string representation of the extreme values of these primitive types, so it is needed to stringify the standard macros such as INT_MIN and INT_MAX.
The normal stringify macros look like this:
#define STRINGIFY(content) #content
#define EXPAND_AND_STRINGIFY(input) STRINGIFY(input)
It works well for EXPAND_AND_STRINGIFY(SHRT_MAX), which will be expanded to "32767".
However, when it going to work with EXPAND_AND_STRINGIFY(SHRT_MIN), it will be expanded to "(-32767 -1)", because #define SHRT_MIN (-SHRT_MAX - 1). This is not what I want. Is there any possible workarounds for it?
No, there is no way to get a preprocessor macro to evaluate an arithmetic expression.
You can get the preprocessor to do arithmetic evaluate, but only in the context of #if, which allows you to evaluate a boolean expression. You can use that feature to rather laboriously output a number, but only by using preprocessor input in #included files, since you cannot put #if inside a macro.
You don't mention why you want to stringify INT_MIN, so I'm not in a position to offer an alternative, if indeed one exists.
However, it's most likely that your best bet is to simply produce the string at run-time, using snprintf.

Working of pre-processor C++

#define NAME VALUE
I know whenever the compiler see this, it would replace NAME with VALUE. But I'm confused about the working of pre-processing directives such as :
#define CONFIG_VAR(name, type, value)
This does not tell the compiler to replace anything , but I could see statements like
CONFIG_VAR(rank, int, 100)
which would compile successfully. How does this work ?
In your example, that would simply do nothing at all. Any arguments, even those that seem like they should give compilation errors, are accepted and the whole macro call is replaced with an empty string.
If, however, you later replace the definition with something like:
#define CONFIG_VAR(name, type, value) add_config_var<type>(name, value)
it would suddenly do something useful. So, I'd guess that macro is a placeholder for functionality which is not (yet) implemented or not available in that part of the program.
When you say:
#define FOO BAR
what the preprocessor does is to replace each time after this it sees the text FOO by the text BAR, a macro definition. The process is called macro expansion. This is mostly used to define constants, like:
#define N 128
#define MASK (~(1 << 4))
It can be (ab)used to do very funky stuff, as it knows nothing of expressions, statements, or anything. So:
#define CONST (1 + 3 << (x))
is actually OK, and will expand to (1 + 3 << (x)) each time it is seen, using the current value of x each time. Also gunk like:
#define START 5 * (1 +
#define END + 5)
followed by START 2 + 3 + 4 END predictably gives 5 * (1 + 2 + 3 + 4 +5)`
There is also the option of defining macros with parameters, like:
#define BAD_SQUARE(x) x * x
which, if called as BAD_SQUARE(a) will expand to a * a. But BAD_SQUARE(a + b) expands to a + b * a + b, which isn't what was intended (presumably...).
This comes from the dark ages of C, today's C/C++ have safer/cleaner mechanisms to get the same result (use const in C++, in C it sadly defines a variable, not a real constant; use inline functions in C/C++ or templates in C++). There is too much code out there that uses this preprocessor usage (and too many fingers who write this way) so it is practically impossible to get rid of this. As a rule of thumb, learn to read code using macros, whiel learning to write code without them (as far as reasonable, there are times when they come mighty handy...).
This is a macro (more common in C than in C++). According to the definition you provided, the preprocessor will remove occurrences of that "function". A common use-case is usually for logging:
#ifdef DEBUG
#define dprintf(...) printf(...)
#else
#define dprintf(...) // This will remove dprintf lines
#endif
In C++, I believe the general convention is to use inline functions as they provide the same value performance-wise, but are also type checked.
If this really is the entire macro definition, then it simply defines this function-like macro to expand to nothing (an empty string). For example, in the source,
CONFIG_VAR(rank, int, 100);
will be transformed into
;
In this case pre-processor simply removes such strings (replaces with nothing). Widely enough used technique.
Here is example where it is important (actually only one of possible usages):
#if DEBUG_ON
#define LOG(level, string) SomeLogger(level, string)
#else
#define LOG(level, string)
#endif
Probably you should get more familiar with C preprocessor.
There is somewhat close technique (X macro) which builds code which handles repeating lists based on defined actions.

How do I force a constant C-expression evaluation for use as a constant in a .S file?

A header file I'm including from /usr/include/**/asm (rudely?) uses simple C expressions to express an offset from a base value, i.e.:
#define __NR_exit (__NR_SYSCALL_BASE+ 1)
Of course, when I #include this into my .S file the resulting preprocessor-produced asm says:
start.S|17| Error: garbage following instruction -- `ldr r7,=$(0+1)'
So, crazy as it sounds, I guess I want the C-preprocessor (or the assembler) to constexpr-evaluate the macro so it can actually be used, despite the C arithmetic + operator and parens in there -- what is the right way to go about doing this?
Please note that this isn't inline asm, but an "out of line" .S file.
Aw boo, it was just because there was an erroneous dollar sign. If you change it to:
ldr r7,=__NR_exit
it seems to compile just fine. I guess as supports basic arithmetic expressions in positions where it expects constants.

Comma operator in a conditional

I have read in a lot of places but I really can't understand the specified behavior in conditionals.
I understand that in assignments it evaluates the first operand, discards the result, then evaluates the second operand.
But for this code, what it supposed to do?
CPartFile* partfile = (CPartFile*)lParam;
ASSERT( partfile != NULL );
bool bDeleted = false;
if (partfile,bDeleted)
partfile->PerformFileCompleteEnd(wParam);
The partfile in the IF was an unnecessary argument, or it have any meaning?
In this case, it is an unnecessary expression, and can be deleted without changing the meaning of the code.
The comma operator performs the expression of the first item, discards the results, then evaluates the result as the last expression.
So partfile,bDeleted would evaulate whatever partfile would, discard that result, then evaluate and return bDeleted
It's useful if you need to evaluate something which has a side-effect (for example, calling a method). In this case, though, it's useless.
For more information, see Wikipedia: Comma operator
bool bDeleted = false;
if (partfile,bDeleted)
partfile->PerformFileCompleteEnd(wParam);
Here, the if statement evaluates partfile,bDeleted, but bDelete is always false, so the expression fails to run. The key question is "what's that all about?". The probable answer is that someone temporarily wanted to prevent the partfile->PerformFileCompleteEnd(wParam); statement from running, perhaps because it was causing some problem or they wanted to ensure later code reported errors properly if that step wasn't performed. So that they're remember how the code used to be, they left the old "if (partfile)" logic there, but added a hardcoded bDeleted variable to document that the partfile->Perform... logic had effectively been "deleted" from the program.
A better way to temporarily disable such code is probably...
#if 0
if (partfile)
partfile->PerformFileCompleteEnd(wParam);
#endif
...though sometimes I try to document the reasoning too...
#ifndef DONT_BYPASS_FILE_COMPLETE_PROCESSING_DURING_DEBUGGING
if (partfile)
partfile->PerformFileCompleteEnd(wParam);
#endif
...or...
if (partFile, !"FIXME remove this after debugging")
partfile->PerformFileCompleteEnd(wParam);
The best choice depends on your tool set and existing habits (e.g. some editors highlight "FIXME" and "TODO" in reverse video so it's hard to miss or grey out #if 0 blocks; you might have particular strings your source-control checkin warns about; preprocessor defines only in debug vs release builds can prevent accidental distribution etc.).
partfile is evaluated, then bDeleted is evaluated and used as the test. Since evaluation of partfile does not have any side effects, removing it from the conditional has no effect.
The comma operator is a rather obscure feature of C/C++. It should not be confused with the comma in initialising lists (ie: int x, int y; ) nor with function call parameter separation comma (ie: func(x, y) ).
The comma operator has one single purpose: to give the programmer a guaranteed order of evaluation of an expression. For almost every operator in C/C++, the order of evaluation of expressions is undefined. If I write
result = x + y;
where x and y are subexpressions, then either x or y can be evaluated first. I cannot know which, it's up to the compiler. If you however write
result = x, y;
the order of evaluation is guaranteed by the standard: left first.
Of course, the uses of this in real world applications are quite limited...