When implementing Annex K of the C standard (Bounds-checking Interfaces), there is the following requirement:
The extensions specified in this annex can be "requested" to be declared by defining __STDC_WANT_LIB_EXT1__ to 1, and requested to not be declared by defining that to 0.
Then there is this paragraph:
Within a preprocessing translation unit, __STDC_WANT_LIB_EXT1_ _ shall be defined identically for all inclusions of any headers from subclause K.3. If __STDC_WANT_LIB_EXT1_ _ is defined differently for any such inclusion, the implementation shall issue a diagnostic as if a preprocessor error directive were used.
I wonder how to implement this. I went ahead and naïvely wrote this (to be included in each affected header):
#ifndef __STDC_WANT_LIB_EXT1__
#ifdef __STDC_WANT_LIB_EXT1_PREVIOUS__
#error __STDC_WANT_LIB_EXT1__ undefined when it was defined previously.
#endif
#else
#ifdef __STDC_WANT_LIB_EXT1_PREVIOUS__
#if __STDC_WANT_LIB_EXT1__ != __STDC_WANT_LIB_EXT1_PREVIOUS__
#error __STDC_WANT_LIB_EXT1__ defined to different value from previous include.
#endif
#else
#define __STDC_WANT_LIB_EXT1_PREVIOUS__ __STDC_WANT_LIB_EXT1__
#endif
#endif
This (of course) does not work for a variety of reasons:
Does not catch the case when __STDC_WANT_LIB_EXT1__ is not defined for the first include, but defined for the second (which should also be caught with an #error)
The #define does not take the value of __STDC_WANT_LIB_EXT1__ (prefixing # would take the symbol as string, going through symbol2value(...) would take the 1 as string).
...
...but if taken as pseudocode it showcases the logic behind it.
I am not that well-versed with more intricate preprocessor business like this, as you are usually told to stay away from macro magic. There has to be a way to implement the quoted requirement; it just doesn't "click" for me.
Any ideas?
To complete the [mcve], put the above code into header.h, and this in testme.c:
#define __STDC_WANT_LIB_EXT1__ 0
#include "header.h"
#define __STDC_WANT_LIB_EXT1__ 1
#include "header.h"
int main() {}
This should trigger the "different value" error message.
#HWalters did set me on the right track:
#ifndef __STDC_WANT_LIB_EXT1__
#ifdef __STDC_WANT_LIB_EXT1_PREVIOUS__
#if __STDC_WANT_LIB_EXT1_PREVIOUS__ != -1
#error __STDC_WANT_LIB_EXT1__ undefined when it was defined earlier.
#endif
#else
#define __STDC_WANT_LIB_EXT1_PREVIOUS__ -1
#endif
#else
#ifdef __STDC_WANT_LIB_EXT1_PREVIOUS__
#if __STDC_WANT_LIB_EXT1__ != __STDC_WANT_LIB_EXT1_PREVIOUS__
#error __STDC_WANT_LIB_EXT1__ redefined from previous value.
#endif
#else
#if __STDC_WANT_LIB_EXT1__ == 0
#define __STDC_WANT_LIB_EXT1_PREVIOUS__ 0
#elif __STDC_WANT_LIB_EXT1__ == 1
#define __STDC_WANT_LIB_EXT1_PREVIOUS__ 1
#else
/* Values other than 0,1 reserved for future use */
#define __STDC_WANT_LIB_EXT1_PREVIOUS__ -2
#endif
#endif
#endif
The "thinko" was this line:
#define __STDC_WANT_LIB_EXT1_PREVIOUS__ __STDC_WANT_LIB_EXT1__
Defining the "previous" to an actual value instand of another token makes it work.
The solution is not perfect, though -- all "other" values except 0,1,undefined get lumped together into a single "previous" value (-2), while the letter of the standard says that any redefinition should issue a diagnostic.
Related
I'm working on some geometry-based code. The task at hand involves use of a bounding-box to contain the solid specimen. Now, in the code I have devised two different types of such boxes, namely INNER_BOUNDING_BOX and OUTER_BOUNDING_BOX. The code further expects use of any one of the two boxes, but not both. I'm trying to achieve it through the use of preprocessor.
I have written further code based on a couple of macros namely USE_INNER_BOUNDING_BOX and USE_OUTER_BOUNDING_BOX. I can ensure that at any time any one macro is defined through some simple construct like this:
#if defined(USE_INNER_BOUNDING_BOX) && defined(USE_OUTER_BOUNDING_BOX)
#undef USE_INNER_BOUNDING_BOX
#undef USE_OUTER_BOUNDING_BOX
#define USE_INNER_BOUNDING_BOX
#endif
#ifndef USE_INNER_BOUNDING_BOX
#ifndef USE_OUTER_BOUNDING_BOX
#define USE_INNER_BOUNDING_BOX
#endif
#endif
Now, if I wanted to use any particular box, I could just define the corresponding macro. The difficulty comes with wanting for use of a default setting macro say USE_DEFAULT_BOUNDING_BOX, which I could use to then set up define for any one of USE_INNER_BOUNDING_BOX or USE_OUTER_BOUNDING_BOX when both or none of them are explicitly defined.
I'd be inclined towards portable code, but compiler-specific trick could also pass. I'm using Visual Studio 2012.
Reliable one-of-many selections like those can better be done by selecting them with a single multi-value switch right away.
#define BOUNDING_INNER 1
#define BOUNDING_OUTER 2
/* default */
#define BOUNDING_BOX_TO_USE BOUNDING_INNER
/* alternatively please activate below line
#define BOUNDING_BOX_TO_USE BOUNDING_OUTER
*/
If you need to stay backward compatible to some configurations,
e.g. your code has already been used by others,
you can derive the single switch from the two, matching your default behaviour.
The advantage is to avoid #undef (in case you agree that it is an advantage to do so).
#if defined(USE_INNER_BOUNDING_BOX) && defined(USE_OUTER_BOUNDING_BOX)
#define BOUNDING_BOX_TO_USE BOUNDING_INNER
#endif
#ifndef USE_INNER_BOUNDING_BOX
#ifndef USE_OUTER_BOUNDING_BOX
#define BOUNDING_BOX_TO_USE BOUNDING_INNER
#endif
#endif
/* In case you are as paranoid a programmer as I am,
you might want to do some plausibility checking
here. ifndef, >0, <2 etc., triggering some #errors. */
/* Later, in code doing the actual implementation: */
#if (BOUNDING_BOX_TO_USE == BOUNDING_INNER)
/* do inner bounding stuff */
#endif
/* other code, e.g. common for inner and outer */
#if (BOUNDING_BOX_TO_USE == BOUNDING_OUTER)
/* do outer bounding stuff */
#endif
Since there are only two values I would use only one boolean variable:
#ifndef USE_OUTER_BOUNDING_BOX
#define USE_OUTER_BOUNDING_BOX 0
#endif
If USE_OUTER_BOUNDING_BOX is zero (false) the inner bounding box is used.
test.c:
#include <stdio.h>
#ifndef USE_OUTER_BOUNDING_BOX
#define USE_OUTER_BOUNDING_BOX 0
#endif
int main(void)
{
printf("%d\n", USE_OUTER_BOUNDING_BOX);
return 0;
}
Example:
$ cc -o test -DUSE_OUTER_BOUNDING_BOX=0 test.c
$ ./test
0
$ cc -o test -DUSE_OUTER_BOUNDING_BOX=1 test.c
$ ./test
1
Here is what I ended with:
// Comment to use bigger outer Bounding-Box
#define USE_INNER_BOUNDING_BOX
#define INNER_BOUNDING_BOX 0
#define OUTER_BOUNDING_BOX 1
#define DEFAULT_BOUNDING_BOX OUTER_BOUNDING_BOX
#if defined(USE_INNER_BOUNDING_BOX) && !defined(USE_OUTER_BOUNDING_BOX)
#define USE_BOUNDING_BOX INNER_BOUNDING_BOX
#elif defined(USE_OUTER_BOUNDING_BOX)
#define USE_BOUNDING_BOX OUTER_BOUNDING_BOX
#else
#define USE_BOUNDING_BOX DEFAULT_BOUNDING_BOX
#endif
#if (USE_BOUNDING_BOX == INNER_BOUNDING_BOX)
#undef USE_OUTER_BOUNDING_BOX
#define USE_INNER_BOUNDING_BOX
#else
#undef USE_INNER_BOUNDING_BOX
#define USE_OUTER_BOUNDING_BOX
#endif
This just works in this case. In case of more boxes, I'd append the conditional blocks.
I made a mechanism for compiling only selected tests from a sequence of tests by defining the macros:
#define SELECTION(x) ((!defined (RUN_SELECTED_TESTS_ONLY)) || (defined (x)))
#define RUN_SELECTED_TESTS_ONLY
#define TEST_1 //Lets say I want only test1 to be compiled
#if SELECTION(TEST_1) //The line I'm getting the error on.
//code of test 1
#endif
#if SELECTION(TEST_2)
//code of test 2
#endif
While compilation I'm getting the error :
error C2003: expected 'defined id'
I'm getting the error only when TEST_1 or TEST_2 (or both) are defined.
An alternative definition for SELECTION:
#ifdef RUN_SELECTED_TESTS_ONLY
#define SELECTION defined
#else
#define SELECTION(x) 1
#endif
Notes:
Must be defined after RUN_SELECTED_TESTS_ONLY is.
Only works in GNU cpp and other preprocessors similarly permissive about operator defined being the result of a macro expansion.
Example:
#define RUN_SELECTED_TESTS_ONLY
#ifdef RUN_SELECTED_TESTS_ONLY
#define SELECTION defined
#else
#define SELECTION(x) 1
#endif
#define TEST_1
//#define TEST_2
#include <stdio.h>
int main()
{
#if SELECTION(TEST_1)
printf("Test 1\n");
#endif
#if SELECTION(TEST_2)
printf("Test 2\n");
#endif
return 0;
}
Output:
Test 1
What you have invokes undefined behaviour. C standard says that the defined preprocessor operator may not appear as a result of replacement.
C11 draft, 6.10.1 Conditional inclusion
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. 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.
If you can't perform same check at run-time, you could do:
#define RUN_SELECTED_TESTS_ONLY
#define TEST_1
#if ((!defined (RUN_SELECTED_TESTS_ONLY)) || (defined (TEST_1)))
//code of test 1
#endif
Basically performing the "selection" yourself.
The error you get means: An identifier must follow the preprocessor keyword. (from MSDN).
It doesn't work because you cannot you defined() 2 times in your macro SELECTION(x).
What you can do instead is something like:
#define SELECTION(x) (!RUN_SELECTED_TESTS_ONLY || x)
#define RUN_SELECTED_TESTS_ONLY 1
#define TEST_1 1
#define TEST_2 0
#if SELECTION(TEST_1)
//some code
#endif
int main() {
printf("%d\n", SELECTION(TEST_1));
printf("%d\n", SELECTION(TEST_2));
return 0;
}
On Apple's opensource website, the entry for stdarg.h contains the following:
#ifndef _STDARG_H
#ifndef _ANSI_STDARG_H_
#ifndef __need___va_list
#define _STDARG_H
#define _ANSI_STDARG_H_
#endif /* not __need___va_list */
#undef __need___va_list
What do the #define statements do if there's nothing following their first argument?
There are sort of three possible "values" for an identifier in the preprocessor:
Undefined: we don't know about this name.
Defined, but empty: we know about this name, but it has no value.
Defined, with value: we know about this name, and it has a value.
The second, defined but empty, is often used for conditional compilation, where the test is simply for the definedness, but not the value, of an identifier:
#ifdef __cplusplus
// here we know we are C++, and we do not care about which version
#endif
#if __cplusplus >= 199711L
// here we know we have a specific version or later
#endif
#ifndef __cplusplus // or #if !defined(__cplusplus)
// here we know we are not C++
#endif
That's an example with a name that if it is defined will have a value. But there are others, like NDEBUG, which are usually defined with no value at all (-DNDEBUG on the compiler command line, usually).
They define a macro which expands to nothing. It's not very useful if you intended it to be used as a macro, but it's very useful when combined with #ifdef and friends—you can, for example, use it to create an include guard, so when you #include a file multiple times, the guarded contents are included only once.
You define something like:
#define _ANSI_STDARG_H_
so that, later you can check for:
#ifdef _ANSI_STDARG_H_
I regularly use object-like preprocessor macros as boolean flags in C code to turn on and off sections of code.
For example
#define DEBUG_PRINT 1
And then use it like
#if(DEBUG_PRINT == 1)
printf("%s", "Testing");
#endif
However, it comes a problem if the header file that contains the #define is forgotten to be included in the source code. Since the macro is not declared, the preprocessor treats it as if it equals 0, and the #if statement never runs.
When the header file is forgotten to be included, non-expected, unruly behaviour can occur.
Ideally, I would like to be able to both check that a macro is defined, and check that it equals a certain value, in one line. If it is not defined, the preprocessor throws an error (or warning).
I'm looking for something along the lines of:
#if-def-and-true-else-throw-error(DEBUG_PRINT)
...
#endif
It's like a combination of #ifdef and #if, and if it doesn't exist, uses #error.
I have explored a few avenues, however, preprocessor directives can't be used inside a #define block, and as far as I can tell, there is no preprocessor option to throw errors/warnings if a macro is not defined when used inside a #if statement.
This may not work for the general case (I don't think there's a general solution to what you're asking for), but for your specific example you might consider changing this sequence of code:
#if(DEBUG_PRINT == 1)
printf("%s", "Testing");
#endif
to:
if (DEBUG_PRINT == 1) {
printf("%s", "Testing");
}
It's no more verbose and will fail to compile if DEBUG_PRINT is not defined or if it's defined to be something that cannot be compared with 1.
as far as I can tell, there is no preprocessor option to throw errors/warnings if a macro is not defined when used inside a #if statement.
It can't be an error because the C standard specifies that behavior is legal. From section 6.10.1/3 of ISO C99 standard:
After all replacements due to macro expansion and the defined unary
operator have been performed, all remaining identifiers are replaced with the pp-number
0....
As Jim Balter notes in the comment below, though, some compilers (such as gcc) can issue warnings about it. However, since the behavior of substituting 0 for unrecognized preprocessor tokens is legal (and in many cases desirable), I'd expect that enabling such warnings in practice would generate a significant amount of noise.
There's no way to do exactly what you want. If you want to generate a compilation failure if the macro is not defined, you'll have to do it explicitly
#if !defined DEBUG_PRINT
#error DEBUG_PRINT is not defined.
#endif
for each source file that cares. Alternatively, you could convert your macro to a function-like macro and avoid using #if. For example, you could define a DEBUG_PRINT macro that expands to a printf call for debug builds but expands to nothing for non-debug builds. Any file that neglects to include the header defining the macro then would fail to compile.
Edit:
Regarding desirability, I have seen numerous times where code uses:
#if ENABLE_SOME_CODE
...
#endif
instead of:
#ifdef ENABLE_SOME_CODE
...
#endif
so that #define ENABLE_SOME_CODE 0 disables the code rather than enables it.
Rather than using DEBUG_PRINT directly in your source files, put this in the header file:
#if !defined(DEBUG_PRINT)
#error DEBUG_PRINT is not defined
#endif
#if DEBUG_PRINT
#define PrintDebug([args]) [definition]
#else
#define PrintDebug
#endif
Any source file that uses PrintDebug but doesn't include the header file will fail to compile.
If you need other code than calls to PrintDebug to be compiled based on DEBUG_PRINT, consider using Michael Burr's suggestion of using plain if rather than #if (yes, the optimizer will not generate code within a false constant test).
Edit:
And you can generalize PrintDebug above to include or exclude arbitrary code as long as you don't have commas that look like macro arguments:
#if !defined(IF_DEBUG)
#error IF_DEBUG is not defined
#endif
#if IF_DEBUG
#define IfDebug(code) code
#else
#define IfDebug(code)
#endif
Then you can write stuff like
IfDebug(int count1;) // IfDebug(int count1, count2;) won't work
IfDebug(int count2;)
...
IfDebug(count1++; count2++;)
Yes you can check both:
#if defined DEBUG && DEBUG == 1
# define D(...) printf(__VA_ARGS__)
#else
# define D(...)
#endif
In this example even when #define DEBUG 0 but it is not equal to 1 thus nothing will be printed.
You can do even this:
#if defined DEBUG && DEBUG
# define D(...) printf(__VA_ARGS__)
#else
# define D(...)
#endif
Here if you #define DEBUG 0 and then D(1,2,3) also nothing will be printed
DOC
Simply create a macro DEBUG_PRINT that does the actual printing:
#define DEBUG_PRINT(n, str) \
\
if(n == 1) \
{ \
printf("%s", str); \
} \
else if(n == 2) \
{ \
do_something_else(); \
} \
\
#endif
#include <stdio.h>
int main()
{
DEBUG_PRINT(1, "testing");
}
If the macro isn't defined, then you will get a compiler error because the symbol is not recognized.
#if 0 // 0/1
#define DEBUG_PRINT printf("%s", "Testing")
#else
#define DEBUG_PRINT printf("%s")
#endif
So when "if 0" it'll do nothing and when "if 1" it'll execute the defined macro.
What is the difference (if any) between the two following preprocessor control statements.
#if
and
#ifdef
You can demonstrate the difference by doing:
#define FOO 0
#if FOO
// won't compile this
#endif
#ifdef FOO
// will compile this
#endif
#if checks for the value of the symbol, while #ifdef checks the existence of the symbol (regardless of its value).
#ifdef FOO
is a shortcut for:
#if defined(FOO)
#if can also be used for other tests or for more complex preprocessor conditions.
#if defined(FOO) || defined(BAR)