Suppose I have a header file with lines like this:
#if LONG_BIT != 8 * SIZEOF_LONG
/* 04-Oct-2000 LONG_BIT is apparently (mis)defined as 64 on some recent
* 32-bit platforms using gcc. We try to catch that here at compile-time
* rather than waiting for integer multiplication to trigger bogus
* overflows.
*/
#error "pp897: LONG_BIT definition appears wrong for platform (bad gcc/glibc config?)."
#endif
I would like to output the value of LONG_BIT and SIZEOF_LONG. Is it possible to do this, or is that impossible from a header file?
_Static_assert in C or static_assert in C++ can test conditions and display a string, and the string can be constructed with preprocessor expansions:
#define LONG_BIT 64
#define SIZEOF_LONG 4
#define StringizeHelper(x) #x
#define Stringize(x) StringizeHelper(x)
_Static_assert(LONG_BIT == 8 * SIZEOF_LONG,
"LONG_BIT is " Stringize(LONG_BIT) " but must be 8 * "
Stringize(SIZEOF_LONG) ".");
Output with Clang:
x.c:7:1: error: static_assert failed "LONG_BIT is 64 but must be 8 * 4."
_Static_assert(LONG_BIT == 8 * SIZEOF_LONG,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
You have a few values to test in that case. You could test the plausible ones one by one like a switch/case statement, with a default just in case.
Standalone example. The 2 first define statements are here for the test, remove from final code
// completely bogus/incoherent values just to test
#define LONG_BIT 32
#define SIZEOF_LONG 4444
// operational test from now on
#if LONG_BIT != 8 * SIZEOF_LONG
#if LONG_BIT == 32
#error "pp897: LONG_BIT definition appears wrong for platform (bad gcc/glibc config?): size 32"
#elif LONG_BIT == 64
#error "pp897: LONG_BIT definition appears wrong for platform (bad gcc/glibc config?): size 64"
#else
#error "pp897: LONG_BIT definition appears wrong for platform (bad gcc/glibc config?): size ???"
#endif
#endif
compilation output:
test.c:7:2: error: #error "pp897: LONG_BIT definition appears wrong for platfo
rm (bad gcc/glibc config?): size 32"
This method is compatible with all standards including C89
With GCC or Clang (at least), you can print out the values of preprocessor macros:
#define LONG_BIT 60
#pragma message "LONG_BIT is " STRINGIFY(LONG_BIT)
But that won't get you the value of sizeof(long), which is not a preprocessor construct. It also won't do arithmetic; LONG_BIT needs to be an actual number for that to produce the desired message.
That doesn't work with #error, which doesn't do macro substitutions in the text.
Here, STRINGIFY has the usual two-stage definition:
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
You can also write the whole message inside the arguments, at least in this case, but watch out for unexpected expansions:
#pragma message STRINGIFY(LONG BIT is LONG_BIT)
Related
I'm wondering if it can be written that the prepocessor evaluates assigned constants known at compile time and returns the result as a string. I believe the answer is no or complex, but I'll give a try.
Basically I have constants which are expressed in milliseconds but I want to display the results as secs, therefore divide by 1000, and wonder because all is known at compile time, if the preprocessor can directly put the result of this division into the code rather than eval at runtime.
Example:
#define FREQ_AUTO_WHEN_RELAY_ON 150000UL
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
STR( FREQ_AUTO_WHEN_RELAY_ON/1000UL ) " secs"
would yield to "150000UL/1000UL secs"
which is not I want to display, aka "150 secs"
Thanks
You have to first prepare a header with all possible outputs:
// calculate.h
#if VALUE == 1
#define RESULT 1
#elif VALUE == 2
#define RESULT 2
/* etc. millions of lines */
#elif VALUE == 150
#define RESULT 150
#endif
Then you can do:
#define VALUE FREQ_AUTO_WHEN_RELAY_ON/1000UL
#include "calculate.h"
STR(VALUE)
Similarly, you first have to define a matrix of all possible combinations of values:
#define DIV_1UL_1UL 1
#define DIV_1UL_2UL 0
#define DIV_2UL_1UL 2
/* etc. really millions of lines */
#define DIV_150000UL_1000UL 150
Then you can:
#define DIV(a, b) DIV_##a##_##b
#define XDIV(a, b) DIV(a, b)
STR(XDIV(FREQ_AUTO_WHEN_RELAY_ON, 1000UL))
Can C-preprocessor can output as a string the evaluation of compiled known constants values(e.g. 150000UL/1000UL)?
Yes, but it's not practical. Instead, generate the header file from a build system.
I have written an amazing kernel which will bring me fame and fortune - if I can only get it to compile with NVRTC:
#include <stdio.h>
__global__ void do_stuff() { }
I would have hoped that system headers should be recognized by the (runtime) compiler, just like a regular compiler, and that this would "just work" (modulo any printf-specific machinery). Alternatively, if it didn't work, I would have expected an error message about stdio.h's source not made available with the "program creation" API call (nvrtcCreateProgram()), since I'm passing NULL and NULL as its last two arguments.
However, what I get is the following:
/usr/include/stdio.h(33): catastrophic error: cannot open source file "stddef.h"
This seems strange to me. It means that the runtime compiler is able to look inside system headers, but is not able to find stddef.h, like nvcc or the host side compiler are able to.
Why is this happening, and what is the idiomatic/recommended workaround?
Note: I'd like a workaround which would be cross-platform, not just work on my individual machine.
Here are two solutions which might work, but which I would rather avoid. If they're the only reasonable course of action after all - please comment and say so:
Add the specific path to stddef.h as a compiler parameter (-I or --include-path=).
Pass the source of stddef.h to the nvrtcCreateProgram() call.
An additional approach is taken in the "JITify" library which Robert Crovella has graciously reminded me of. While this doesn't seem to be document very well, Jitify pre-includes processed snippets of various headers it sees fit to. In particular for <climits>/<limits.h>:
static const char* jitsafe_header_limits_h = R"(
#pragma once
#if defined _WIN32 || defined _WIN64
#define __WORDSIZE 32
#else
#if defined __x86_64__ && !defined __ILP32__
#define __WORDSIZE 64
#else
#define __WORDSIZE 32
#endif
#endif
#define MB_LEN_MAX 16
#define CHAR_BIT 8
#define SCHAR_MIN (-128)
#define SCHAR_MAX 127
#define UCHAR_MAX 255
enum {
_JITIFY_CHAR_IS_UNSIGNED = (char)-1 >= 0,
CHAR_MIN = _JITIFY_CHAR_IS_UNSIGNED ? 0 : SCHAR_MIN,
CHAR_MAX = _JITIFY_CHAR_IS_UNSIGNED ? UCHAR_MAX : SCHAR_MAX,
};
#define SHRT_MIN (-32768)
#define SHRT_MAX 32767
#define USHRT_MAX 65535
#define INT_MIN (-INT_MAX - 1)
#define INT_MAX 2147483647
#define UINT_MAX 4294967295U
#if __WORDSIZE == 64
# define LONG_MAX 9223372036854775807L
#else
# define LONG_MAX 2147483647L
#endif
#define LONG_MIN (-LONG_MAX - 1L)
#if __WORDSIZE == 64
#define ULONG_MAX 18446744073709551615UL
#else
#define ULONG_MAX 4294967295UL
#endif
#define LLONG_MAX 9223372036854775807LL
#define LLONG_MIN (-LLONG_MAX - 1LL)
#define ULLONG_MAX 18446744073709551615ULL
)";
for stddef.h:
static const char* jitsafe_header_stddef_h =
"#pragma once\n"
"#include <climits>\n"
"namespace __jitify_stddef_ns {\n"
"#if __cplusplus >= 201103L\n"
"typedef decltype(nullptr) nullptr_t;\n"
"#if defined(_MSC_VER)\n"
" typedef double max_align_t;\n"
"#elif defined(__APPLE__)\n"
" typedef long double max_align_t;\n"
"#else\n"
" // Define max_align_t to match the GCC definition.\n"
" typedef struct {\n"
" long long __jitify_max_align_nonce1\n"
" __attribute__((__aligned__(__alignof__(long long))));\n"
" long double __jitify_max_align_nonce2\n"
" __attribute__((__aligned__(__alignof__(long double))));\n"
" } max_align_t;\n"
"#endif\n"
"#endif // __cplusplus >= 201103L\n"
"#if __cplusplus >= 201703L\n"
"enum class byte : unsigned char {};\n"
"#endif // __cplusplus >= 201703L\n"
"} // namespace __jitify_stddef_ns\n"
"namespace std {\n"
" // NVRTC provides built-in definitions of ::size_t and ::ptrdiff_t.\n"
" using ::size_t;\n"
" using ::ptrdiff_t;\n"
" using namespace __jitify_stddef_ns;\n"
"} // namespace std\n"
"using namespace __jitify_stddef_ns;\n";
and for stdio.h:
static const char* jitsafe_header_stdio_h =
"#pragma once\n"
"#include <stddef.h>\n"
"#define FILE int\n"
"int fflush ( FILE * stream );\n"
"int fprintf ( FILE * stream, const char * format, ... );\n";
If you include those strings as headers, with the appropriate names as keys, it is likely your kernel will compile.
In fact, one could form header files out of these and other mini-headers in jitify.hpp, to use in non-NVRTC kernel compilation. That might be useful too.
One last point: The constants above do not specify a __device__ execution space. So, either you add __device__ in there, or tell the compiler to assume functions are intended for execution on the device only, unless otherwise specified; that's the --device-as-default-execution-space NVRTC compiler option.
The problem:
I'm writing a general C library for an LCD in a microcontroller project.
up to 8 LCDs with various sizes(e.g. 128*96 or 64*48) in various addresses may be added (e.g. LCD3 and LCD7). but only one of them is actively coded at a time. so I thought for a mechanism to do so.
in the code, there is a definition for CLCD_ROWS and CLCD_COLS which correspond to the Active display size.
#define CLCD_ROWS // Active LCD rows
#define CLCD_COLS // Active LCD columns
and there's definitions for the various LCDs. for example, if we have LCD3 and LCD7 connected, we define their sizes with :
#define CLCD_ROWS3 96
#define CLCD_COLS3 64
#define CLCD_ROWS7 128
#define CLCD_COLS7 32
The question:
I've written a [wrong] macro to redefine the values of CLCD_ROWS and CLCD_COLS :
#define cLcd_setActiveI2CcLcd(X) \
CLCD_ROWS = CLCD_ROWS##X \
CLCD_COLS = CLCD_COLS##X
and in my main code I call the macro:
cLcd_setActiveI2CcLcd(7);
which gives me an error of "missing ;".
it is easy to implement it with variables. but since these values are hardcoded , I thought they are "preprocessable" since need every bit of RAM in a low end MCU.
Is my approach about preprocessing this values, correct ?
What is the right way to write a macro for that purpose ?
I'm using a C99 compiler.
First things first, your method of using function-type macro is wrong. Even if you fix the error you have, the macro will not do CLCD_ROWS equal to CLCD_ROWS7, but to CLCD_ROWSX (that is how macros work, it concatenates the thing you give, not its value). Instead if you want to use macros for reducing RAM usage you can change your code to:
1st Solution
#define ROW_COLS 7 // change this if you use different display
#if ROW_COLS == 7
#define CLCD_ROWS 128
#define CLCD_COLS 32
#elif ROW_COLS == 3
#define CLCD_ROWS 96
#define CLCD_COLS 64
#endif
2nd Solution
If you want dynamically change the size of your display in the runtime, you can do it like this:
static int display_cnt;
#define CLCD_ROWS ((display_cnt == 3) ? 96 : 128)
#define CLCD_COLS ((display_cnt == 3) ? 64 : 32)
So when you change the value of display_cnt variable, the macro will automatically change its value.
Below are the contents of /usr/include/x86_64-linux-gnu/gnu/stubs-32.h file:
#include <bits/wordsize.h>
#if __WORDSIZE == 32
# include <gnu/stubs-32.h>
#elif __WORDSIZE == 64
# include <gnu/stubs-64.h>
#else
# error "unexpected value for __WORDSIZE macro"
#endif
I am on 64 Bit machine, so the result of
#include<stdio.h>
main()
{
printf("Word size : %d\n",__WORDSIZE);
}
is
Word size : 64
So here is the question, what is the role of the system variable __WORDSIZE?
I am developing a 32 bit application( using mingw 32 bit compiler) and since my __WORDSIZE is 64 bit, the file /usr/include/x86_64-linux-gnu/gnu/stubs-32.h ultimately results in including /usr/include/x86_64-linux-gnu/gnu/stubs-64.h. I am confused about this part. What are the consequences of this action? Is this normal and if not how can I forcibly include /usr/include/x86_64-linux-gnu/gnu/stubs-32.h?
Thank You in advance.
It is a manifest constant, intended for internal use by the compiler implementation exclusively; that its name is prefixed by two underscores is a clear indicator that it is not intended for use in user space.
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.