C preprocessor parameter bracket covering the 'defined' keyword - c

#if (defined AAAA) //rather than- #if defined (AAAA)
#define BBB (0)
#else
#define BBB (1)
#endif
In the first line above, the parameter bracket includes the "defined" keyword, is there a scenario where this can cause any problem? I know the usual way would be-
#if defined (AAAA)

The syntax of expressions involving defined is specified in section 6.10.1p1 of the C standard (link goes to N1570, which is the closest approximation to the official text of C2011 that is publicly available for free). There are two forms:
defined identifier
or
defined ( identifier )
with exactly the same meaning. In other words, function-call parentheses around the argument of defined are optional.
In your hypothetical
#if (defined AAAA)
this is a use of the first form, with the optional argument parentheses omitted, and an extra set of grouping parentheses around the whole expression. It's interpreted the same as if you had put an extra set of grouping parentheses around a regular if expression containing a unary operation:
if (! variable) /* ... */
is the same as
if ((! variable)) /* ... */
In most of the C codebases I've worked on, the preferred style was to use exclusively defined identifier without the parentheses. I've never seen (defined identifier). It's possible that this used to be a more complicated construct, e.g.
#if (defined A && defined B) || defined C
where the parentheses are necessary, if only because nobody can remember which of && and || has higher precedence.

defined may be used as an ordinary operator inside #if directives.
C 2018 6.10.1 1 says:
The expression that controls conditional inclusion shall be an integer constant expression except that: identifiers (including those lexically identical to keywords) are interpreted as described below and it may contain unary operator expressions of the form
defined identifier
or
defined ( identifier )
which evaluate to 1 if the identifier is currently defined as a macro name (that is, if it is predefined or if it has been the subject of a #define preprocessing directive without an intervening #undef directive with the same subject identifier), 0 if it is not.
Thus, there is no requirement that a #if directive using defined have defined as the sole or top-level operator. It may appear anywhere in an expression, including inside parentheses or even as:
#if defined x + defined y + defined z == 2
which would test whether exactly two of x, y, and z are defined.
Also note that parentheses are not required; using defined (AAAA) instead of defined AAAA just adds clutter.

Related

Order of evaluation in #if directive: macro expansion vs the "defined" keyword

When the c preprocessor runs an #if/#elif preprocessing directive, it performs 4 operations on the tokens that directly follow:
Replace every occurrence of defined {identifier} with 1 if {identifier} is defined, 0 otherwise.
Invoke all macros.
Replace every remaining identifier with 0.
Parse and evaluate the result as a constant-expression.
Now, it's pretty clear from the standard (c99, 6.10.1) that steps 3 and 4 actually happen in that order, and after 1 and 2 are completed. But I can't find any clarification on the order of 1 and 2.
From some limited testing I did, it seems that gcc executes steps 1 and 2 based on the ordering of the tokens - in defined MACRO, the defined executes first, but in MACRO(defined ID) the macro does.
Is this behavior required by the standard? Implementation-defined? Undefined?
Your step 2 is performed first. The order is steps 2, 1, 3, 4:
C 2018 6.10.1 4 says [emphasis mine]:
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…
6.10.1 1 says that the controlling expression of an #if or #elif shall be an integer constant expression which may additionally contain the expressions defined identifier or defined ( identifier ) which:
… evaluate to 1 if the identifier is currently defined as a macro name (that is, if it is predefined or if it has been the subject of a #define preprocessing directive without an intervening #undef directive with the same subject identifier), 0 if it is not.
Thus, first macro replacement is performed, per 6.10.1 4, and later the evaluation of the expression is performed.
Note that, in spite of the fact that macro replacement occurs first, if it generates defined tokens, they are not necessarily evaluated, because 6.10.1 4 goes on to say:
… If the token defined is generated as a result of this replacement process…, the behavior is undefined.
Then your step 3 occurs, again per 6.10.1 4:
… 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…
Then the controlling expression is evaluated, your step 4:
… The resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6…

Double nested parentheses throw an error inside macro when using the defined operator

I am writing an emulator and I want it to be exactly like macros in C. The following code confuses me:
This is valid code and returns true:
#if ((((1 + ((2)))))) == 3
This is also valid code and returns true:
#define hi hello
#if defined (hi)
But this will throw an error and not compile:
#define hi hello
#if defined ((hi))
Is there a special reason why this does not work?
It seems like it should work.
Here is a link if you want to test macros online: https://godbolt.org/ (put -E as argument)
Here a link that explains the defined operator: https://gcc.gnu.org/onlinedocs/gcc-8.4.0/cpp/Defined.html
#if does a mathematical evaluation. Your parenthesis get evaluated as in a C expression. The more the merrier, they don't change the value the expression evaluates to (except when they do, of course, when set to change operator precedence).
#ifdef identifier / #if defined identifier / #if defined( identifier ) (the parenthesis are optional for the defined operator, and not allowed for #ifdef) checks if the given identifier is defined. An identifier begins with a letter or an underscore, and contains only letters, underscores, or digits.
hi is an identifier.
(hi) is not.
C 2018 6.10.1 specifies the behavior of define in a #if or #elif directive. It says the expression that controls conditional inclusion:
… may contain unary operator expressions of the form
defined identifier
or
defined ( identifier )
which evaluate to 1 if the identifier is currently defined as a macro
name…
Thus, the operand of defined is not a general C expression but is only “identifier” or “( identifier )”.

Working of conditional compilation #if and #else (and others) in c

I tried to write a program using some conditional compilation pre-processing directives instead of "if-else" as follows.
#include<stdio.h>
int main ()
{
int x;
scanf ("%d",&x);
#if (x==5)
printf ("x is 5");
#else
printf ("x not 5");
#endif
}
But the thing is, it always print the else part even though value of xis 5. My simplest question is----->WHY?
Is it possible to successfully complete this program (i.e taking value of x from user and check conditions using #if directive and print statement under #if).
During compilation it shows a warning "'x' is not defined, evaluates to 0". But x seems defined to me. Does that mean x should be defined using #define. Please explain me concept behind Conditional Compilation.
x is not an integer literal or an integer literal expression (integer literals + operators) or a macro expanding to those, so in a conditional, the preprocessor replaces it with 0 (6.10.1p4). 0==5 is false, so the #else branch is taken.
The preprocessor doesn't know about C declarations, types and such. It only works with tokens (and macros that ultimately expand to those).
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.
Preprocessing takes place before the compilation. So preprocessor does not know anything about your C code or variables. You cant use any C variables in conditions.
Conditional compilation is for different purposes.
#define DEBUG
/* ....*/
#ifdef DEBUG
printf("Some debug value %d\n", val);
#endif
Operands in #if statements can be only constants, things defined with #define, and a special defined operator. Any other identifiers in the expression are replaced with 0. The x in your sample code is not defined with #define, so (x==5) becomes (0==0).
In the C 2018 standard, clause 6.10.1 tells us that evaluation of the expression in an #if statement includes:
Preprocessor macros (things defined with #define) are replaced according to their definitions.
Uses of the defined operator are replaced with 0 or 1.
Any remaining identifiers are replaced with 0.
Because the x in your sample code is not defined with #define, it is replaced with 0 in the #if statement. This results in (0==5), which is false, so code between the #if and the #else is skipped.
In a preprocessor statement, you cannot evaluate variables based on values that will be set during program execution.
It's the "pre-processor". "Pre" means "before".
You're trying to use a runtime value during preprocessing! The preprocessor of course has no access to that information during the build.
This problem isn't limited to runtime values, but is more fundamental. Even if you were trying to use a (named) compile-time constant such as constexpr int x = 2, you couldn't do that. These are two languages interleaving, like generating HTML with PHP; the HTML has no knowledge of PHP variables, and the PHP has no knowledge of what widgets the user clicks on the page. These are completely different execution contexts with no built-in interaction or cross-compatibility.

Macro name must be an identifier

please, tell me what's wrong with this code:
// part of main.c
#if have(some_macro)
printf("Import succeeded!\n");
#else
# error Import failed!
#endif
// part of utils.h
#define have(macro) defined(macro)
If I write just #if defined(some_macro) it works.
What's the problem?
You cannot have anything following #if expand to defined. That is subject to undefined behavior.
From the C99 Standard (emphasis mine):
6.10.1 Conditional inclusion
...
3 Preprocessing directives of the forms
# if *constant-expression new-line group<sub>opt</sub>*
# elif *constant-expression new-line group<sub>opt</sub>*
check whether the controlling constant expression evaluates to nonzero.
4 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.

Is it correct to say if any non-macro variable that is used in a conditional directive evaluates to 0?

Let's say I have the following piece of code. Is it correct to say that the conditional directive always evaluates to zero since M is expanded before compile time where the value of i is zero according to C specification? Could someone explain it if I'm wrong:
#include <stdio.h>
#define M i
int main() {
int i = 10;
#if M == 0
i = 0;
#endif
printf("%d", i);
return 0;
}
With #if identifiers that are not macros are all considered to be the number zero. The gcc docs for #if lay out the requirements nicel, which says (emphasis mine going forward):
#if expression
expression is a C expression of integer type, subject to stringent restrictions. It may contain
Integer constants.
Character constants, which are interpreted as they would be in normal code.
Arithmetic operators for addition, subtraction, multiplication, division, bitwise operations, shifts, comparisons, and logical operations (&& and ||). The latter two obey the usual short-circuiting rules of standard C.
Macros. All macros in the expression are expanded before actual computation of the expression's value begins.
Uses of the defined operator, which lets you check whether macros are defined in the middle of an ‘#if’.
Identifiers that are not macros, which are all considered to be the number zero. This allows you to write #if MACRO instead of #ifdef MACRO, if you know that MACRO, when defined, will always have a nonzero value. Function-like macros used without their function call parentheses are also treated as zero.
and notes that:
In some contexts this shortcut is undesirable. The -Wundef option causes GCC to warn whenever it encounters an identifier which is not a macro in an ‘#if’.
This is covered in the draft C99 standard section 6.10.1 Conditional inclusion paragraph 4 which says:
[...]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.[...]
Yes, they are treated as the number 0.
C11 §6.10.1 Conditional inclusion
... 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.
pp-number here refers to preprocessing numbers in §6.4.8.

Resources