How to initialize an array of structures with variable index - c

I have structure like below
typedef struct
{
int a;
int b;
int c;
} my_struct;
and in another file I have declared a variable of this my_struct type, like below.
my_struct strct_arr[MAX];
Where MAX is a macro which is a configurable value that is a multiple of 18 (18 or 36 or 54 and so on.. it may go up to 18*n times).
I have to initialize the structure with {0xff,0,0}. So, how to initialize whole array of structure my_struct strct_arr[MAX]; with my initial values without using any kind of loops.
I am expecting the output as below:
my_struct strct_arr[MAX]={
{0xff,0,0},
{0xff,0,0},
{0xff,0,0},
{0xff,0,0},
…
};
But without knowing MAX value, how to initialize it?

There is GCC extension for this. Try this
#define MAX 18
my_struct strct_arr[MAX]={ [0 ... (MAX - 1)] = {0xff,0,0}};
Check https://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Designated-Inits.html

Yes, this is possible using the C preprocessor!
#include <stdio.h>
#include <boost/preprocessor/repetition/repeat.hpp>
#define INITS(z, n, t) { 0xFF, 0, 0 },
#define REP(item, n) BOOST_PP_REPEAT(n, INITS, item)
#define MAX 123
typedef struct { int a,b,c; } my_struct;
my_struct ms[] = { REP(, MAX) };
int main()
{
// Check it worked
printf("%d\n", (int)(sizeof ms / sizeof *ms));
}
Note: boost is a package of C++ stuff, however the boost/preprocessor just uses the preprocessor features which are common to both languages. If your implementation doesn't allow this #include by default, you can find a copy of repeat.hpp from the boost source code.
Also, BOOST_PP_REPEAT defaults to a max of 256. If your MAX is bigger than this, you can edit repeat.hpp to allow bigger values, it should be obvious what to do from there.
Note: this post describes a system for recursive macro that would not require the same sort of implementation as repeat.hpp uses, but I haven't been able to get it to work.
Credit: this post

Well, there's is no direct and immediate syntax in standard C to specify an initializer that would do what you want. If you wanted to initialize the whole thing with zeros, then = { 0 } would work regardless of size, but that 0xff makes it a completely different story. GCC compiler supports a non-standard extension that works in such cases (see Sanket Parmar's answers for details), but alas it is not standard.
There's also a non-standard memcpy hack that is sometimes used to fill memory regions with repetitive patterns. In your case it would look as follows
my_struct strct_arr[MAX] = { { 0xff, 0, 0 } };
memcpy(strct_arr + 1, strct_arr, sizeof strct_arr - sizeof *strct_arr);
But this is a hack, since it relies on memcpy doing its copying in byte-by-byte fashion and in strictly left-to-right direction (i.e. from smaller memory addresses to larger ones). However, that's not guaranteed by the language specification. If you want to "legalize" this trick, you have to write your own version of my_memcpy that works in that way specifically (byte-by-byte, left-to-right) and use it instead. Of course, this is formally a cyclic solution that is not based entirely on initializer syntax.

Paraphrasing Jonathan Leffler's solution:
struct my_struct { char c, int a; int b; }
#define MAX 135
#define INIT_X_1 { 0xff, 0, 0 }
#define INIT_X_2 INIT_X_1, INIT_X_1
#define INIT_X_4 INIT_X_2, INIT_X_2
#define INIT_X_8 INIT_X_4, INIT_X_4
#define INIT_X_16 INIT_X_8, INIT_X_8
#define INIT_X_32 INIT_X_16, INIT_X_16
#define INIT_X_64 INIT_X_32, INIT_X_32
#define INIT_X_128 INIT_X_64, INIT_X_64
struct my_struct strct_arr[MAX] =
{
#if (MAX & 1)
INIT_X_1,
#endif
#if (MAX & 2)
INIT_X_2,
#endif
#if (MAX & 4)
INIT_X_4,
#endif
#if (MAX & 8)
INIT_X_8,
#endif
#if (MAX & 16)
INIT_X_16,
#endif
#if (MAX & 32)
INIT_X_32,
#endif
#if (MAX & 64)
INIT_X_64,
#endif
#if (MAX & 128)
INIT_X_128,
#endif
};

Just for sake of variety, since you know the array will be a multiple of 18, you could use something like this:
#define INIT_X_1 { 0xff, 0, 0 }
#define INIT_X_3 INIT_X_1, INIT_X_1, INIT_X_1
#define INIT_X_9 INIT_X_3, INIT_X_3, INIT_X_3
#define INIT_X_18 INIT_X_9, INIT_X_9
my_struct strct_arr[MAX] =
{
INIT_X_18,
#if MAX > 18
INIT_X_18,
#if MAX > 36
INIT_X_18,
#endif
#endif
};
This will work without needing C99 support (it would even work with pre-standard C), GCC extensions, or Boost Preprocessor library. In every other respect, the other solutions are better.

Related

How to pass string as prefix of defined macro

Is there any idea to pass C string as part of the defined macro like below code?
#define AAA_NUM 10
#define BBB_NUM 20
#define PREFIX_NUM(string) string##_NUM
int main()
{
char *name_a = "AAA";
char *name_b = "AAA";
printf("AAA_NUM: %d\n", PREFIX_NUM(name_a));
printf("BBB_NUM: %d\n", PREFIX_NUM(name_b));
return 0;
}
Expected output
AAA_NUM: 10
BBB_NUM: 20
As mentioned in other posts, you can't use run-time variables in the pre-processor. You could however create enum that way. Though it is usually not a good idea to generate identifiers with macros either, save for special cases like when maintaining an existing code base and you are limited in how much of the existing code you can/want to change. So it should be used as a last resort only.
The least bad way to write such macros would be by using a common design pattern called "X macros". These are used when it is important that code repetition should be reduced to a single place in the project. They tend to make the code look rather alien though... Example:
#define PREFIX_LIST(X) \
/* pre val */ \
X(AAA, 10) \
X(BBB, 20) \
X(CCC, 30) \
enum // used to generate constants like AAA_NUM = 10,
{
#define PREFIX_ENUMS(pre, val) pre##_NUM = (val),
PREFIX_LIST(PREFIX_ENUMS)
};
#include <stdio.h>
int main (void)
{
// one way to print
#define prefix_to_val(pre) pre##_NUM
printf("AAA_NUM: %d\n", prefix_to_val(AAA));
printf("BBB_NUM: %d\n", prefix_to_val(BBB));
// another alternative
#define STR(s) #s
#define print_all_prefixes(pre, val) printf("%s: %d\n", STR(pre##_NUM), val);
PREFIX_LIST(print_all_prefixes)
return 0;
}
A macro is only processed before compilation and not at runtime. Your code example does not work as you can see here.
Good practice (for example MISRA coding rules) recommend to use macros as little as possible since it is error prone.
Preprocessor works at compile time and here name_a and name_b are non constant, and even if they were (i.e. const char *str is a real constant in C++ but not in C), there is a literal substitution and the preprocessor does not know the contents of variables.
This works (notice that the parameter should be expanded by another macro in order to get a valid token):
#include <stdio.h>
#define AAA_NUM 10
#define BBB_NUM 20
#define _PREFIX_NUM(string) string##_NUM
#define PREFIX_NUM(string) _PREFIX_NUM(string)
int main(void)
{
#define name_a AAA
#define name_b BBB
printf("AAA_NUM: %d\n", PREFIX_NUM(name_a));
printf("BBB_NUM: %d\n", PREFIX_NUM(name_b));
return 0;
}
There is no way in C to create runtime symbols and use them. C is a compiled language and all symbols have to be known before the compilation.
The preprocessor (which do changes on the text level before the compilation) does not know anything about the C language.

In Brian Gladman's AES implementation, how is aes_encrypt_key128 being mapped to aes_xi?

I'm able to follow the code path up to a certain point. Briefly:
The program accepts an ASCII hexadecimal string and converts it to binary. https://github.com/BrianGladman/aes/blob/master/aesxam.c#L366-L382
If arg[3] is an “E”, it defines an aes_encrypt_ctx struct and passes the key, the calculated key_len value, and the aes_encrypt_ctx stuct to aes_encrypt_key. https://github.com/BrianGladman/aes/blob/master/aesxam.c#L409-L412
aes_encrypt_key is defined in aeskey.c. Depending on key_len, the function aes_encrypt_key<NNN> is called. They key and the struct are passed to the function. https://github.com/BrianGladman/aes/blob/master/aeskey.c#L545-L547
But where is the aes_encrypt_key128 function?
This line appears to be my huckleberry:
# define aes_xi(x) aes_ ## x
So hopefully I'm onto something. It's mapping aes_encrypt_key128 to aes_xi(encrypt_key128), right?
AES_RETURN aes_xi(encrypt_key128)(const unsigned char *key, aes_encrypt_ctx cx[1])
{ uint32_t ss[4];
cx->ks[0] = ss[0] = word_in(key, 0);
cx->ks[1] = ss[1] = word_in(key, 1);
cx->ks[2] = ss[2] = word_in(key, 2);
cx->ks[3] = ss[3] = word_in(key, 3);
#ifdef ENC_KS_UNROLL
ke4(cx->ks, 0); ke4(cx->ks, 1);
ke4(cx->ks, 2); ke4(cx->ks, 3);
ke4(cx->ks, 4); ke4(cx->ks, 5);
ke4(cx->ks, 6); ke4(cx->ks, 7);
ke4(cx->ks, 8);
#else
{ uint32_t i;
for(i = 0; i < 9; ++i)
ke4(cx->ks, i);
}
#endif
ke4(cx->ks, 9);
cx->inf.l = 0;
cx->inf.b[0] = 10 * AES_BLOCK_SIZE;
#ifdef USE_VIA_ACE_IF_PRESENT
if(VIA_ACE_AVAILABLE)
cx->inf.b[1] = 0xff;
#endif
MARK_AS_ENCRYPTION_CTX(cx);
return EXIT_SUCCESS;
}
I see some pattern replacement happening here. I guess at this point I was wondering if you could point me to the docs that explain this feature of #define?
Here are some docs which explain token concatenation. You can also take this as a suggestion about where to search systematically for reliable docs:
The C standard. At this website you can download WG14 N1570, which is quite similar to the C11 standard (it's a pre-standard draft, but it's basically the same as the standard except you don't have to pay for it.) There's an HTML version of this document at http://port70.net/~nsz/c/c11/n1570.html, which is handy for constructing links. With that in mind, I can point you at the actual standard definition of ## in §6.10.3.3 of the standard.
The C standard can be a bit rough going if you're not already an expert in C. It makes very few concessions for learners. A more readable document is Gnu GCC's C Preprocessor (CPP) manual, although it is does not always distinguish between standard features and GCC extensions. Still, it's quite readable and there's lots of useful information. The ## operator is explained in Chapter 3.5
cppreference.com is better known as a C++ reference site, but it also contains documentation about C. It's language is almost as telegraphic as the C++/C standards, and it is not always 100% accurate (although it is very good), but it has several advantages. For one thing, it combines documentation for different standard versions, so it is really useful for knowing when a feature entered the language (and consequently which compiler version you will need to use the feature). Also, it is well cross-linked, so it's very easy to navigate. Here's what it has to say about the preprocessor; you'll find documentation about ## here.
I've been at this a while but it started to become clear to me that there is pattern matching going on in the pre-processing macros of the aeskey.c file. The only doc I've been able to find is this one.
Pattern Matching
The ## operator is used to concatenate two tokens into one token. This
is provides a very powerful way to do pattern matching. Say we want to
write a IIF macro, we could write it like this:
#define IIF(cond) IIF_ ## cond
#define IIF_0(t, f) f
#define IIF_1(t, f) t
However there is one problem with this approach. A subtle side effect
of the ## operator is that it inhibits expansion. Heres an example:
#define A() 1
//This correctly expands to true
IIF(1)(true, false)
// This will however expand to
IIF_A()(true, false)
// This is because A() doesn't expand to 1,
// because its inhibited by the ## operator
IIF(A())(true, false)
The way to work around this is to use another indirection. Since this
is commonly done we can write a macro called CAT that will concatenate
without inhibition.
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
So now we can write the IIF macro (its called IIF right now, later we
will show how to define a more generalized way of defining an IF
macro):
#define IIF(c) PRIMITIVE_CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t
#define A() 1
//This correctly expands to true
IIF(1)(true, false)
// And this will also now correctly expand to true
IIF(A())(true, false)
With pattern matching we can define other operations, such as COMPL
which takes the complement:
#define COMPL(b) PRIMITIVE_CAT(COMPL_, b)
#define COMPL_0 1
#define COMPL_1 0
or BITAND:
#define BITAND(x) PRIMITIVE_CAT(BITAND_, x)
#define BITAND_0(y) 0
#define BITAND_1(y) y
We can define increment and decrement operators as macros:
#define INC(x) PRIMITIVE_CAT(INC_, x)
#define INC_0 1
#define INC_1 2
#define INC_2 3
#define INC_3 4
#define INC_4 5
#define INC_5 6
#define INC_6 7
#define INC_7 8
#define INC_8 9
#define INC_9 9
#define DEC(x) PRIMITIVE_CAT(DEC_, x)
#define DEC_0 0
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8

Are there directives in C/C++ preprocessor to convert string to number?

I wish to add some conditional directive in my code to control different build, for example:
#if VERSION > 100
/* Compiling here */
#endif
The problem is that 'VERSION' is in other's code where I can't change. It was defined as a string:
#define VERSION "101"
I'm wondering if there's some sort of macro or directive which converts the string to number so I can simply do
#if STRING_TO_NUMBER(VERSION) > 100
/* Compiling here */
#endif
Is that possible please?
PS.
It seems my description is not quite clear. The main purpose of this requirement is to control the version branch. For example, in old version, pre-version 100, this program would like old_function(). After this version, all functions have been migrated to new_function. So I need to write codes like that:
#if VERSION >= 100
old_function();
#else
new_function();
#endif
#if VERSION >= 100
int old_function()
{
...
}
#else
int new_function()
{
...
}
#endif
You can see that only one of the function will be compiled. Therefore the condition must be decided in preprocessing stage, not in the runtime.
The tricky part is, the VERSION had been defined as a string, which brought this question.
If you need to interact with the pre-processor to set other #defines or conditionally #include different headers. Until you can get VERSION to be "fixed" to be an integer...
The only thing that I can think of for you to do is to create a tiny header file defining PROPER_VERSION and include it by naming each file as the version number. So here you would create:
100:
#define PROPER_VERSION 100
101:
#define PROPER_VERSION 101
102:
#define PROPER_VERSION 102
and then you would need to add the following:
#include VERSION
And then use PROPER_VERSION as you need
#if PROPER_VERSION > 100
...
Its not elegant, but I cannot see anything else you can do. You can auto-generate the VERSION file.
As long as you don't need to make declarations or preprocessor defines conditional on VERSION, and as long as you are confident that the VERSION string will just be an integer with no leading zeros, (both of which might be too much to ask for), you might be able to do this at compile time if your compiler has a reasonably effective constant expression evaluator.
For example, gcc 4.8 will optimize away the following if test, leaving only the appropriate arm:
if (strlen(VERSION) > 3 || (strlen(VERSION) == 3 && strcmp(VERSION, "100") > 0)) {
// code if VERSION is at least "101"
} else {
// code if VERSION is "100" or less
}
The fact that only one of the branches of the if statement survives the compilation is easily demonstrated by inserting a call to an undefined function in the non-used branch. With gcc (and clang), and with optimization enabled, no linker error is produced:
#include <stdio.h>
#include <string.h>
#define VERSION "101"
// This function is not available for linking
int unknown_function();
// This one is in standard library
int rand();
int main(void) {
int x;
if (strlen(VERSION) > 3 || (strlen(VERSION) == 3 && strcmp(VERSION, "100") > 0)) {
// code if VERSION is at least "101"
x = rand();
} else {
// code if VERSION is "100" or less
x = unknown_function();
}
printf("%d\n", x);
return 0;
}
(See it at http://ideone.com/nGLGTH)
In C++11, there is an even more clearly compile-time version. You can create a constexpr version of atoi. Combined with what some might call an abuse of templates, that allows for conditional declarations:
constexpr int const_atoi(const char* num, int accum=0) {
return *num ? const_atoi(num+1, accum*10 + (*num - '0')) : accum;
}
template<bool V_GT_100> struct MoreOrLess_Impl;
template<> struct MoreOrLess_Impl<false> {
// Old prototype
void doit(double x) {...}
};
template<> struct MoreOrLess_Impl<true> {
// New prototype
void doit(long double x) {...}
};
using MoreOrLess = MoreOrLess_Impl<(const_atoi(VERSION) > 100)>;
// ...
// ... MoreOrLess::doit(x) ...
(Silly example at http://ideone.com/H1sdNg)

Platform independent storage of c bitfields

I use C bitfields to store data in memory. For archive usage these data has to be written to a file (and later on be combined with data from another machine). It seems to be a bad idea to save the bitfields directly to the file, since the arrangement of data is implementation specific.
For this reason I wrote some methods to "serialize" these bitfields to save them in a unified format:
/* uint16 is a unsigned int with size 16 */
typedef struct {
uint16 a : 1;
/* ... just examples ... */
uint16 z : 13;
} data;
void save_data(FILE* fp, data d) {
uint16 tmp;
tmp = d.a;
fwrite(&tmp,sizeof(uint16),1,fp);
/* ... */
tmp = d.z;
fwrite(&tmp,sizeof(uint16),1,fp);
}
While this is perfectly working, it seems not to be well to extend, since adding more members in data requires adding the data to the save routine as well.
Is there any trick to automatically convert bitfield data to a unified format without needing to adapt the routine/macro when changing the bitfield data?
Here is one method. I cannot recommend it, but it's out there and it sort of works, so why not look at it. This incarnation is still platform-dependent but you can easily switch to a platform-independent, possibly human-readable format. Error handling is omitted for brevity.
// uglymacro.h
#if defined(DEFINE_STRUCT)
#define BEGINSTRUCT(struct_tag) typedef struct struct_tag {
#define ENDSTRUCT(struct_typedef) } struct_typedef;
#define BITFIELD(name,type,bit) type name : bit;
#define FIELD(name,type) type name;
#define ARRAYFIELD(name,type,size) type name[size];
#elif defined(DEFINE_SAVE)
#define BEGINSTRUCT(struct_tag) void save_##struct_tag(FILE* fp, \
struct struct_tag* p_a) {
#define ENDSTRUCT(struct_typedef) }
#define BITFIELD(name,type,bit) { type tmp; tmp = p_a->name; \
fwrite (&tmp, sizeof(type), 1, fp); }
#define FIELD(name,type) { fwrite (&p_a->name, sizeof(p_a->name), 1, fp); }
#define ARRAYFIELD(name,type,size) { fwrite (p_a->name, sizeof(p_a->name[0]), size, fp); }
#elif defined(DEFINE_READ)
#define BEGINSTRUCT(struct_tag) void read_##struct_tag(FILE* fp, \
struct struct_tag* p_a) {
#define ENDSTRUCT(struct_typedef) }
#define BITFIELD(name,type,bit) { type tmp; fread (&tmp, sizeof(type), 1, fp); \
p_a->name = tmp; }
#define FIELD(name,type) { fread (&p_a->name, sizeof(p_a->name), 1, fp); }
#define ARRAYFIELD(name,type,size) { fread (p_a->name, sizeof(p_a->name[0]), size, fp); }
#else
#error "Must define either DEFINE_STRUCT or DEFINE_SAVE or DEFINE_READ"
#endif
#undef DEFINE_STRUCT
#undef DEFINE_READ
#undef DEFINE_WRITE
#undef BEGINSTRUCT
#undef ENDSTRUCT
#undef FIELD
#undef BITFIELD
#undef ARRAYFIELD
Your struct definition looks like this:
// mystruct_def.h
BEGINSTRUCT(mystruct)
BITFIELD(a,int,1)
FIELD(b,int)
ARRAYFIELD(c,int,10)
ENDSTRUCT(mystruct)
You use it like this:
// in mystruct.h file
#define DEFINE_STRUCT
#include "uglymacro.h"
#include "mystruct_def.h"
// in mystruct.c file
#include "mystruct.h"
#define DEFINE_READ
#include "mystruct_def.h"
#define DEFINE_WRITE
#include "mystruct_def.h"
Frankly, by modern standards this method is ugly. I have used something similar about 20 years ago and it was ugly back then.
Another alternative is using a more humane code-generation facility instead of the C preprocessor.
If you are willing to invest a bit you can use tools like P99 for "statement unrolling":
// in header
#define MY_BITFIELDS a, z
#define WRITE_IT(X) fwrite(&(unsigned){ d.X }, sizeof(unsigned), 1, fp)
#define WRITE_ALL(...) P99_SEP(WRITE_IT, __VA_ARGS__)
// in your function
WRITE_ALL(MY_BITFIELDS);
BTW, never use int for bitfields if you can avoid this. The semantic of a set of bits is much better matched by unsigned.
With a bit of more macro coding you could even use something like
#define MY_BITFIELDS (a, 1), (z, 11)
to produce the struct declaration and the write part.
Why not use a human readable text format?
typedef struct {
int a : 1;
/* ... just examples ... */
int z : 13;
} data;
void save_data(FILE* fp, data d) {
fprintf( fp, "a:%d\n", d.a );
fprintf( fp, "b:%d\n", d.b );
...
fprintf( fp, "z:%d\n", d.z );
}
The advantage of this technique is that somebody using any different language could quickly write a parser to load your data on any machine, any architecture.

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