Asterisk in the argument name with C preprocessor - c

I want to implement cross-platform build of my DLL with mingw32/VC.
At the moment everything is perfect with mingw side. However I have to wrap several things in macro for VC (it is built as /TC), for example:
void __attribute__((fastcall)) do1 ( A*, B , C, D );
bool __attribute__((fastcall)) ( *do2 ) ( E*, F );
The first one is simple, just a macro:
#ifdef __MINGW32__
#define __FASTCALL__ __attribute__((fastcall))
#elif _MSC_VER
#define __FASTCALL__ __fastcall
#else
#error "unsupported compiler"
#endif
The problem comes with the second one. Calling convention with a function pointer should looks like
bool ( __fastcall *do2 ) ( E*, F );
I tried the following macro (I skipped ifdef part):
#define __FASTCALLP__(func) (__attribute__((fastcall))(*##func))
#define __FASTCALLP__(func) (__fastcall *##func)
or if pass function name with asterisk:
#define __FASTCALLP__(func) (__attribute__((fastcall))(##func))
#define __FASTCALLP__(func) (__fastcall ##func)
Both failed with
error: pasting "*" and "function_name" does not give a valid
preprocessing token
May I wrong at my approach at all? Or I have to ifdef the whole code blocks or separate it to different files?

The problem is with the Concatenation-Operator ##. It will produce a new preprocessor token by concatenating the left- and right-hand-side, which does not exists (*do2 is no defined token)
Simply omit it and write like this (omitting #ifdefs):
#define __FASTCALL__(func) (__attribute__((fastcall))(func))
#define __FASTCALL__(func) (__fastcall func)
and use like this:
bool __FASTCALL__(do1)(A*, B , C, D);
bool __FASTCALL__(*do2)(E*, F);

Related

#define IDENTIFIER without a token

What does the following statement mean:
#define FAHAD
I am familiar with the statements like:
#define FAHAD 1
But what does the #define statement without a token signify?
Is it that it is similar to a constant definition?
Defining a constant without a value acts as a flag to the preprocessor, and can be used like so:
#define MY_FLAG
#ifdef MY_FLAG
/* If we defined MY_FLAG, we want this to be compiled */
#else
/* We did not define MY_FLAG, we want this to be compiled instead */
#endif
it means that FAHAD is defined, you can later check if it's defined or not with:
#ifdef FAHAD
//do something
#else
//something else
#endif
Or:
#ifndef FAHAD //if not defined
//do something
#endif
A real life example use is to check if a function or a header is available for your platform, usually a build system will define macros to indicate that some functions or headers exist before actually compiling, for example this checks if signal.h is available:
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif/*HAVE_SIGNAL_H*/
This checks if some function is available
#ifdef HAVE_SOME_FUNCTION
//use this function
#else
//else use another one
#endif
Any #define results in replacing the original identifier with the replacement tokens. If there are no replacement tokens, the replacement is empty:
#define DEF_A "some stuff"
#define DEF_B 42
#define DEF_C
printf("%s is %d\n", DEF_A, DEF_B DEF_C);
expands to:
printf("%s is %d\n", "some stuff", 42 );
I put a space between 42 and ) to indicate the "nothing" that DEF_C expanded-to, but in terms of the language at least, the output of the preprocessor is merely a stream of tokens. (Actual compilers generally let you see the preprocessor output. Whether there will be any white-space here depends on the actual preprocessor. For GNU cpp, there is one.)
As in the other answers so far, you can use #ifdef to test whether an identifier has been #defined. You can also write:
#if defined(DEF_C)
for instance. These tests are positive (i.e., the identifier is defined) even if the expansion is empty.
#define FAHAD
this will act like a compiler flag, under which some code can be done.
this will instruct the compiler to compile the code present under this compiler option
#ifdef FAHAD
printf();
#else
/* NA */
#endif

Letting a function only be called using a macro

I am developing my own assert function in C, and is is declared in my header file as:
void Certify_Continuity( const char* expression, const int line, const char* file );
It should be called using a macro defined as:
#if !defined ( ENABLE_DEBUG ) || defined ( __CALLE__ )
#define DEBUG_ASSERT( e ) (void)(e)
#else
#define DEBUG_ASSERT( e ) ( e ) ? (void)0 : Certify_Continuity( #e, __LINE__, __FILE__ )
#endif
The problem here is that the programmers are able to call Certify_Continuity directly.
Is there any technique to disallow the user to call the function directly, allowing him only to call it using the macro?
A macro is just textual (token) substitution performed before the compiler proper runs, so you can't prevent someone from just manually expanding the macro and removing the parts they don't like.
However, you can make it arbitrarily difficult and dangerous for someone to do this. For example, you can omit the declaration of Certify_Continuity from the header file, and just declare it inline like this:
#define DEBUG_ASSERT(e) do { \
extern void Certify_Continuity( const char* expression, const int line, const char* file ); \
if(!(e)) Certify_Continuity(#e, __LINE__, __FILE__); \
} while(0)
This way, anyone who calls the function directly has to declare the prototype first.
You can also name it in such a way that others will think twice about calling it:
void DO_NOT_CALL__USE_DEBUG_ASSERT__Certify_Continuity(...)
Of course, if someone is determined enough to bypass you, and doesn't care about the crazy wart sticking out of their code, then that's their problem. If they work for or alongside you, that's when you use externalities like code review to block this behaviour.
You could use the trick in C that (foo)() calls the function foo, whereas foo() expands the macro foo (under the assumption that both exists).
In you case, your macro should look like:
#if !defined ( ENABLE_DEBUG ) || defined ( __CALLE__ )
#define DEBUG_ASSERT( e ) (void)(e)
#else
#define DEBUG_ASSERT( e ) ( e ) ? (void)0 : (Certify_Continuity)( #e, __LINE__, __FILE__ )
#endif
#define Certify_Continuity(x,y,z) YOU_SHOULD_NOT_CALL_Certify_Continuity()
If the user tries to call Certify_Continuity directly, an error is issued that YOU_SHOULD_NOT_CALL_Certify_Continuity doesn't exist.
Of course, this can't prevent the user from calling it like (Certify_Continuity)().

Correct #if functionality

If I define
#if SOMETHING
#endif
and I have not defined SOMETHING anywhere. Would the code inside #if compile ?
When the name used in the argument expression of #if is not defined as a macro (after all other macro replacement is finished), it is replaced with 0. This means that your #if SOMETHING will be interpreted as #if 0. The code under #if will be removed by preprocessor.
The rule applies to more complex expressions as well. You can do
#define A 42
#if A + B
which will evaluate to #if 42, since unknown name B is interpreted as 0
No, as long as SOMETHING is also not one of the predfined macros or a macro passed on the commandline to the compiler.
I think in C99 it defaults to 0 while in C89 it does not as here its giving me an error
Source code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define A 42
#define B
int main(int argc, char *argv[]){
int c;
#if A
c = A + B;
#endif
printf("%d\n",c);
return 0;
}
Error :
error: expected expression before ‘;’ token
No, because as an undefined macro, it would not necessarily be replaced with anything... but that is probably compiler specifc, and not to be trusted.
You may want to use:
#ifdef DEFINED_WORD
#ifndef DEFINED_WORD
Where DEFINED_WORD is declared by a #define, like: #define DEFINED_WORD. The ifdef construct ONLY compiles the code between that and the #endif if DEFINED_WORD was defined. The opposite is true of #ifndef. You can nest them like so:
#ifdef DEFINED_WORD
printf ( "DEFINED_WORD is defined\n" );
#ifndef DEFINED_WORD
printf ( "This line will NEVER print\n" );
#endif
printf ( "This line will print if DEFINED_WORD is defined\n" );
#endif
printf ( "This line will ALWAYS print.\n" );
In my code, I have constructs like:
#ifdef DEBUG
printf ( "array[%d] = %d\n", i, array[i] );
#endif
To deactivate all of the DEBUG code, just comment out the line that you MUST have before calling that #ifdef (top of the source file, or in an included header which you included at the top of the source file, in good form). #define DEBUG
Hope that helps.

What are the applications of the ## preprocessor operator and gotchas to consider?

As mentioned in many of my previous questions, I'm working through K&R, and am currently into the preprocessor. One of the more interesting things — something I never knew before from any of my prior attempts to learn C — is the ## preprocessor operator. According to K&R:
The preprocessor operator ##
provides a way to concatenate actual
arguments during macro expansion. If a
parameter in the replacement text is
adjacent to a ##, the parameter is
replaced by the actual argument, the
## and surrounding white space are
removed, and the result is re-scanned.
For example, the macro paste
concatenates its two arguments:
#define paste(front, back) front ## back
so paste(name, 1) creates the token
name1.
How and why would someone use this in the real world? What are practical examples of its use, and are there gotchas to consider?
One thing to be aware of when you're using the token-paste ('##') or stringizing ('#') preprocessing operators is that you have to use an extra level of indirection for them to work properly in all cases.
If you don't do this and the items passed to the token-pasting operator are macros themselves, you'll get results that are probably not what you want:
#include <stdio.h>
#define STRINGIFY2( x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#define PASTE2( a, b) a##b
#define PASTE( a, b) PASTE2( a, b)
#define BAD_PASTE(x,y) x##y
#define BAD_STRINGIFY(x) #x
#define SOME_MACRO function_name
int main()
{
printf( "buggy results:\n");
printf( "%s\n", STRINGIFY( BAD_PASTE( SOME_MACRO, __LINE__)));
printf( "%s\n", BAD_STRINGIFY( BAD_PASTE( SOME_MACRO, __LINE__)));
printf( "%s\n", BAD_STRINGIFY( PASTE( SOME_MACRO, __LINE__)));
printf( "\n" "desired result:\n");
printf( "%s\n", STRINGIFY( PASTE( SOME_MACRO, __LINE__)));
}
The output:
buggy results:
SOME_MACRO__LINE__
BAD_PASTE( SOME_MACRO, __LINE__)
PASTE( SOME_MACRO, __LINE__)
desired result:
function_name21
CrashRpt: Using ## to convert macro multi-byte strings to Unicode
An interesting usage in CrashRpt (crash reporting library) is the following:
#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
//Note you need a WIDEN2 so that __DATE__ will evaluate first.
Here they want to use a two-byte string instead of a one-byte-per-char string. This probably looks like it is really pointless, but they do it for a good reason.
std::wstring BuildDate = std::wstring(WIDEN(__DATE__)) + L" " + WIDEN(__TIME__);
They use it with another macro that returns a string with the date and time.
Putting L next to a __ DATE __ would give you a compiling error.
Windows: Using ## for generic Unicode or multi-byte strings
Windows uses something like the following:
#ifdef _UNICODE
#define _T(x) L ## x
#else
#define _T(x) x
#endif
And _T is used everywhere in code
Various libraries, using for clean accessor and modifier names:
I've also seen it used in code to define accessors and modifiers:
#define MYLIB_ACCESSOR(name) (Get##name)
#define MYLIB_MODIFIER(name) (Set##name)
Likewise you can use this same method for any other types of clever name creation.
Various libraries, using it to make several variable declarations at once:
#define CREATE_3_VARS(name) name##1, name##2, name##3
int CREATE_3_VARS(myInts);
myInts1 = 13;
myInts2 = 19;
myInts3 = 77;
Here's a gotcha that I ran into when upgrading to a new version of a compiler:
Unnecessary use of the token-pasting operator (##) is non-portable and may generate undesired whitespace, warnings, or errors.
When the result of the token-pasting operator is not a valid preprocessor token, the token-pasting operator is unnecessary and possibly harmful.
For example, one might try to build string literals at compile time using the token-pasting operator:
#define STRINGIFY(x) #x
#define PLUS(a, b) STRINGIFY(a##+##b)
#define NS(a, b) STRINGIFY(a##::##b)
printf("%s %s\n", PLUS(1,2), NS(std,vector));
On some compilers, this will output the expected result:
1+2 std::vector
On other compilers, this will include undesired whitespace:
1 + 2 std :: vector
Fairly modern versions of GCC (>=3.3 or so) will fail to compile this code:
foo.cpp:16:1: pasting "1" and "+" does not give a valid preprocessing token
foo.cpp:16:1: pasting "+" and "2" does not give a valid preprocessing token
foo.cpp:16:1: pasting "std" and "::" does not give a valid preprocessing token
foo.cpp:16:1: pasting "::" and "vector" does not give a valid preprocessing token
The solution is to omit the token-pasting operator when concatenating preprocessor tokens to C/C++ operators:
#define STRINGIFY(x) #x
#define PLUS(a, b) STRINGIFY(a+b)
#define NS(a, b) STRINGIFY(a::b)
printf("%s %s\n", PLUS(1,2), NS(std,vector));
The GCC CPP documentation chapter on concatenation has more useful information on the token-pasting operator.
This is useful in all kinds of situations in order not to repeat yourself needlessly. The following is an example from the Emacs source code. We would like to load a number of functions from a library. The function "foo" should be assigned to fn_foo, and so on. We define the following macro:
#define LOAD_IMGLIB_FN(lib,func) { \
fn_##func = (void *) GetProcAddress (lib, #func); \
if (!fn_##func) return 0; \
}
We can then use it:
LOAD_IMGLIB_FN (library, XpmFreeAttributes);
LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
LOAD_IMGLIB_FN (library, XpmReadFileToImage);
LOAD_IMGLIB_FN (library, XImageFree);
The benefit is not having to write both fn_XpmFreeAttributes and "XpmFreeAttributes" (and risk misspelling one of them).
A previous question on Stack Overflow asked for a smooth method of generating string representations for enumeration constants without a lot of error-prone retyping.
Link
My answer to that question showed how applying little preprocessor magic lets you define your enumeration like this (for example) ...;
ENUM_BEGIN( Color )
ENUM(RED),
ENUM(GREEN),
ENUM(BLUE)
ENUM_END( Color )
... With the benefit that the macro expansion not only defines the enumeration (in a .h file), it also defines a matching array of strings (in a .c file);
const char *ColorStringTable[] =
{
"RED",
"GREEN",
"BLUE"
};
The name of the string table comes from pasting the macro parameter (i.e. Color) to StringTable using the ## operator. Applications (tricks?) like this are where the # and ## operators are invaluable.
You can use token pasting when you need to concatenate macro parameters with something else.
It can be used for templates:
#define LINKED_LIST(A) struct list##_##A {\
A value; \
struct list##_##A *next; \
};
In this case LINKED_LIST(int) would give you
struct list_int {
int value;
struct list_int *next;
};
Similarly you can write a function template for list traversal.
The main use is when you have a naming convention and you want your macro to take advantage of that naming convention. Perhaps you have several families of methods: image_create(), image_activate(), and image_release() also file_create(), file_activate(), file_release(), and mobile_create(), mobile_activate() and mobile_release().
You could write a macro for handling object lifecycle:
#define LIFECYCLE(name, func) (struct name x = name##_create(); name##_activate(x); func(x); name##_release())
Of course, a sort of "minimal version of objects" is not the only sort of naming convention this applies to -- nearly the vast majority of naming conventions make use of a common sub-string to form the names. It could me function names (as above), or field names, variable names, or most anything else.
I use it in C programs to help correctly enforce the prototypes for a set of methods that must conform to some sort of calling convention. In a way, this can be used for poor man's object orientation in straight C:
SCREEN_HANDLER( activeCall )
expands to something like this:
STATUS activeCall_constructor( HANDLE *pInst )
STATUS activeCall_eventHandler( HANDLE *pInst, TOKEN *pEvent );
STATUS activeCall_destructor( HANDLE *pInst );
This enforces correct parameterization for all "derived" objects when you do:
SCREEN_HANDLER( activeCall )
SCREEN_HANDLER( ringingCall )
SCREEN_HANDLER( heldCall )
the above in your header files, etc. It is also useful for maintenance if you even happen to want to change the definitions and/or add methods to the "objects".
SGlib uses ## to basically fudge templates in C. Because there's no function overloading, ## is used to glue the type name into the names of the generated functions. If I had a list type called list_t, then I would get functions named like sglib_list_t_concat, and so on.
I use it for a home rolled assert on a non-standard C compiler for embedded:
#define ASSERT(exp) if(!(exp)){ \
print_to_rs232("Assert failed: " ## #exp );\
while(1){} //Let the watchdog kill us
I use it for adding custom prefixes to variables defined by macros. So something like:
UNITTEST(test_name)
expands to:
void __testframework_test_name ()
One important use in WinCE:
#define BITFMASK(bit_position) (((1U << (bit_position ## _WIDTH)) - 1) << (bit_position ## _LEFTSHIFT))
While defining register bit description we do following:
#define ADDR_LEFTSHIFT 0
#define ADDR_WIDTH 7
And while using BITFMASK, simply use:
BITFMASK(ADDR)
It is very useful for logging. You can do:
#define LOG(msg) log_msg(__function__, ## msg)
Or, if your compiler doesn't support function and func:
#define LOG(msg) log_msg(__file__, __line__, ## msg)
The above "functions" logs message and shows exactly which function logged a message.
My C++ syntax might be not quite correct.

Ways to ASSERT expressions at build time in C

I'm tidying up some older code that uses 'magic numbers' all over the place to set hardware registers, and I would like to use constants instead of these numbers to make the code somewhat more expressive (in fact they will map to the names/values used to document the registers).
However, I'm concerned that with the volume of changes I might break the magic numbers. Here is a simplified example (the register set is more complex):
const short mode0 = 0;
const short mode1 = 1;
const short mode2 = 2;
const short state0 = 0;
const short state1 = 4;
const short state2 = 8;
so instead of :
set_register(5);
we have:
set_register(state1|mode1);
What I'm looking for is a build time version of:
ASSERT(5==(state1|mode1));
Update
#Christian, thanks for the quick response, I'm interested on a C / non-boost environment answer too because this is driver/kernel code.
NEW ANSWER :
In my original answer (below), I had to have two different macros to support assertions in a function scope and at the global scope. I wondered if it was possible to come up with a single solution that would work in both scopes.
I was able to find a solution that worked for Visual Studio and Comeau compilers using extern character arrays. But I was able to find a more complex solution that works for GCC. But GCC's solution doesn't work for Visual Studio. :( But adding a '#ifdef __ GNUC __', it's easy to choose the right set of macros for a given compiler.
Solution:
#ifdef __GNUC__
#define STATIC_ASSERT_HELPER(expr, msg) \
(!!sizeof \ (struct { unsigned int STATIC_ASSERTION__##msg: (expr) ? 1 : -1; }))
#define STATIC_ASSERT(expr, msg) \
extern int (*assert_function__(void)) [STATIC_ASSERT_HELPER(expr, msg)]
#else
#define STATIC_ASSERT(expr, msg) \
extern char STATIC_ASSERTION__##msg[1]; \
extern char STATIC_ASSERTION__##msg[(expr)?1:2]
#endif /* #ifdef __GNUC__ */
Here are the error messages reported for STATIC_ASSERT(1==1, test_message); at line 22 of test.c:
GCC:
line 22: error: negative width in bit-field `STATIC_ASSERTION__test_message'
Visual Studio:
test.c(22) : error C2369: 'STATIC_ASSERTION__test_message' : redefinition; different subscripts
test.c(22) : see declaration of 'STATIC_ASSERTION__test_message'
Comeau:
line 22: error: declaration is incompatible with
"char STATIC_ASSERTION__test_message[1]" (declared at line 22)
ORIGINAL ANSWER :
I do something very similar to what Checkers does. But I include a message that'll show up in many compilers:
#define STATIC_ASSERT(expr, msg) \
{ \
char STATIC_ASSERTION__##msg[(expr)?1:-1]; \
(void)STATIC_ASSERTION__##msg[0]; \
}
And for doing something at the global scope (outside a function) use this:
#define GLOBAL_STATIC_ASSERT(expr, msg) \
extern char STATIC_ASSERTION__##msg[1]; \
extern char STATIC_ASSERTION__##msg[(expr)?1:2]
There is an article by
Ralf Holly that examines different options for static asserts in C.
He presents three different approaches:
switch case values must be unique
arrays must not have negative dimensions
division by zero for constant expressions
His conclusion for the best implementation is this:
#define assert_static(e) \
do { \
enum { assert_static__ = 1/(e) }; \
} while (0)
Checkout boost's static assert
You can roll your own static assert if you don't have access to a third-party library static assert function (like boost):
#define STATIC_ASSERT(x) \
do { \
const static char dummy[(x)?1:-1] = {0};\
} while(0)
The downside is, of course, that error message is not going to be very helpful, but at least, it will give you the line number.
#define static_assert(expr) \
int __static_assert(int static_assert_failed[(expr)?1:-1])
It can be used anywhere, any times.
I think it is the easiest solution.
Before usage, test it with your compiler carefully.
Any of the techniques listed here should work and when C++0x becomes available you will be able to use the built-in static_assert keyword.
If you have Boost then using BOOST_STATIC_ASSERT is the way to go. If you're using C or don't want to get Boost
here's my c_assert.h file that defines (and explains the workings of) a few macros to handle static assertions.
It's a bit more convoluted that it should be because in ANSI C code you need 2 different macros - one that can work in the area where you have declarations and one that can work in the area where normal statements go. There is a also a bit of work that goes into making the macro work at global scope or in block scope and a bunch of gunk to ensure that there are no name collisions.
STATIC_ASSERT() can be used in the variable declaration block or global scope.
STATIC_ASSERT_EX() can be among regular statements.
For C++ code (or C99 code that allow declarations mixed with statements) STATIC_ASSERT() will work anywhere.
/*
Define macros to allow compile-time assertions.
If the expression is false, an error something like
test.c(9) : error XXXXX: negative subscript
will be issued (the exact error and its format is dependent
on the compiler).
The techique used for C is to declare an extern (which can be used in
file or block scope) array with a size of 1 if the expr is TRUE and
a size of -1 if the expr is false (which will result in a compiler error).
A counter or line number is appended to the name to help make it unique.
Note that this is not a foolproof technique, but compilers are
supposed to accept multiple identical extern declarations anyway.
This technique doesn't work in all cases for C++ because extern declarations
are not permitted inside classes. To get a CPP_ASSERT(), there is an
implementation of something similar to Boost's BOOST_STATIC_ASSERT(). Boost's
approach uses template specialization; when expr evaluates to 1, a typedef
for the type
::interslice::StaticAssert_test< sizeof( ::interslice::StaticAssert_failed<true>) >
which boils down to
::interslice::StaticAssert_test< 1>
which boils down to
struct StaticAssert_test
is declared. If expr is 0, the compiler will be unable to find a specialization for
::interslice::StaticAssert_failed<false>.
STATIC_ASSERT() or C_ASSERT should work in either C or C++ code (and they do the same thing)
CPP_ASSERT is defined only for C++ code.
Since declarations can only occur at file scope or at the start of a block in
standard C, the C_ASSERT() or STATIC_ASSERT() macros will only work there. For situations
where you want to perform compile-time asserts elsewhere, use C_ASSERT_EX() or
STATIC_ASSERT_X() which wrap an enum declaration inside it's own block.
*/
#ifndef C_ASSERT_H_3803b949_b422_4377_8713_ce606f29d546
#define C_ASSERT_H_3803b949_b422_4377_8713_ce606f29d546
/* first some utility macros to paste a line number or counter to the end of an identifier
* this will let us have some chance of generating names that are unique
* there may be problems if a static assert ends up on the same line number in different headers
* to avoid that problem in C++ use namespaces
*/
#if !defined( PASTE)
#define PASTE2( x, y) x##y
#define PASTE( x, y) PASTE2( x, y)
#endif /* PASTE */
#if !defined( PASTE_LINE)
#define PASTE_LINE( x) PASTE( x, __LINE__)
#endif /* PASTE_LINE */
#if!defined( PASTE_COUNTER)
#if (_MSC_VER >= 1300) /* __COUNTER__ introduced in VS 7 (VS.NET 2002) */
#define PASTE_COUNTER( x) PASTE( x, __COUNTER__) /* __COUNTER__ is a an _MSC_VER >= 1300 non-Ansi extension */
#else
#define PASTE_COUNTER( x) PASTE( x, __LINE__) /* since there's no __COUNTER__ use __LINE__ as a more or less reasonable substitute */
#endif
#endif /* PASTE_COUNTER */
#if __cplusplus
extern "C++" { // required in case we're included inside an extern "C" block
namespace interslice {
template<bool b> struct StaticAssert_failed;
template<> struct StaticAssert_failed<true> { enum {val = 1 }; };
template<int x> struct StaticAssert_test { };
}
}
#define CPP_ASSERT( expr) typedef ::interslice::StaticAssert_test< sizeof( ::interslice::StaticAssert_failed< (bool) (expr) >) > PASTE_COUNTER( IntersliceStaticAssertType_)
#define STATIC_ASSERT( expr) CPP_ASSERT( expr)
#define STATIC_ASSERT_EX( expr) CPP_ASSERT( expr)
#else
#define C_ASSERT_STORAGE_CLASS extern /* change to typedef might be needed for some compilers? */
#define C_ASSERT_GUID 4964f7ac50fa4661a1377e4c17509495 /* used to make sure our extern name doesn't collide with something else */
#define STATIC_ASSERT( expr) C_ASSERT_STORAGE_CLASS char PASTE( PASTE( c_assert_, C_ASSERT_GUID), [(expr) ? 1 : -1])
#define STATIC_ASSERT_EX(expr) do { enum { c_assert__ = 1/((expr) ? 1 : 0) }; } while (0)
#endif /* __cplusplus */
#if !defined( C_ASSERT) /* C_ASSERT() might be defined by winnt.h */
#define C_ASSERT( expr) STATIC_ASSERT( expr)
#endif /* !defined( C_ASSERT) */
#define C_ASSERT_EX( expr) STATIC_ASSERT_EX( expr)
#ifdef TEST_IMPLEMENTATION
C_ASSERT( 1 < 2);
C_ASSERT( 1 < 2);
int main( )
{
C_ASSERT( 1 < 2);
C_ASSERT( 1 < 2);
int x;
x = 1 + 4;
C_ASSERT_EX( 1 < 2);
C_ASSERT_EX( 1 < 2);
return( 0);
}
#endif /* TEST_IMPLEMENTATION */
#endif /* C_ASSERT_H_3803b949_b422_4377_8713_ce606f29d546 */
Try:
#define STATIC_ASSERT(x, error) \
do { \
static const char error[(x)?1:-1];\
} while(0)
Then you can write:
STATIC_ASSERT(a == b, a_not_equal_to_b);
Which may give you a better error message (depending on your compiler).
The common, portable option is
#if 5 != (state1|mode1)
# error "aaugh!"
#endif
but it doesn't work in this case, because they're C constants and not #defines.
You can see the Linux kernel's BUILD_BUG_ON macro for something that handles your case:
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
When condition is true, this becomes ((void)sizeof(char[-1])), which is illegal and should fail at compile time, and otherwise it becomes ((void)sizeof(char[1])), which is just fine.
Ensure you compile with a sufficiently recent compiler (e.g. gcc -std=c11).
Then your statement is simply:
_Static_assert(state1|mode1 == 5, "Unexpected change of bitflags");
#define MODE0 0
#define MODE1 1
#define MODE2 2
#define STATE0 0
#define STATE1 4
#define STATE2 8
set_register(STATE1|STATE1); //set_register(5);
#if (!(5==(STATE1|STATE1))) //MY_ASSERT(5==(state1|mode1)); note the !
#error "error blah blah"
#endif
This is not as elegant as a one line MY_ASSERT(expr) solution. You could use sed, awk, or m4 macro processor before compiling your C code to generate the DEBUG code expansion of MY_ASSERT(expr) to multiple lines or NODEBUG code which removes them for production.

Resources