compile time check for enums [duplicate] - c

Is there a compile-time way to detect / prevent duplicate values within a C/C++ enumeration?
The catch is that there are multiple items which are initialized to explicit values.
Background:
I've inherited some C code such as the following:
#define BASE1_VAL (5)
#define BASE2_VAL (7)
typedef enum
{
MsgFoo1A = BASE1_VAL, // 5
MsgFoo1B, // 6
MsgFoo1C, // 7
MsgFoo1D, // 8
MsgFoo1E, // 9
MsgFoo2A = BASE2_VAL, // Uh oh! 7 again...
MsgFoo2B // Uh oh! 8 again...
} FOO;
The problem is that as the code grows & as developers add more messages to the MsgFoo1x group, eventually it overruns BASE2_VAL.
This code will eventually be migrated to C++, so if there is a C++-only solution (template magic?), that's OK -- but a solution that works with C and C++ is better.

There are a couple ways to check this compile time, but they might not always work for you. Start by inserting a "marker" enum value right before MsgFoo2A.
typedef enum
{
MsgFoo1A = BASE1_VAL,
MsgFoo1B,
MsgFoo1C,
MsgFoo1D,
MsgFoo1E,
MARKER_1_DONT_USE, /* Don't use this value, but leave it here. */
MsgFoo2A = BASE2_VAL,
MsgFoo2B
} FOO;
Now we need a way to ensure that MARKER_1_DONT_USE < BASE2_VAL at compile-time. There are two common techiques.
Negative size arrays
It is an error to declare an array with negative size. This looks a little ugly, but it works.
extern int IGNORE_ENUM_CHECK[MARKER_1_DONT_USE > BASE2_VAL ? -1 : 1];
Almost every compiler ever written will generate an error if MARKER_1_DONT_USE is greater than BASE_2_VAL. GCC spits out:
test.c:16: error: size of array ‘IGNORE_ENUM_CHECK’ is negative
Static assertions
If your compiler supports C11, you can use _Static_assert. Support for C11 is not ubiquitous, but your compiler may support _Static_assert anyway, especially since the corresponding feature in C++ is widely supported.
_Static_assert(MARKER_1_DONT_USE < BASE2_VAL, "Enum values overlap.");
GCC spits out the following message:
test.c:16:1: error: static assertion failed: "Enum values overlap."
_Static_assert(MARKER_1_DONT_USE < BASE2_VAL, "Enum values overlap.");
^

I didn't see "pretty" in your requirements, so I submit this solution implemented using the Boost Preprocessor library.
As an up-front disclaimer, I haven't used Boost.Preprocessor a whole lot and I've only tested this with the test cases presented here, so there could be bugs, and there may be an easier, cleaner way to do this. I certainly welcome comments, corrections, suggestions, insults, etc.
Here we go:
#include <boost/preprocessor.hpp>
#define EXPAND_ENUM_VALUE(r, data, i, elem) \
BOOST_PP_SEQ_ELEM(0, elem) \
BOOST_PP_IIF( \
BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE(elem), 2), \
= BOOST_PP_SEQ_ELEM(1, elem), \
BOOST_PP_EMPTY()) \
BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(data, BOOST_PP_ADD(i, 1)))
#define ADD_CASE_FOR_ENUM_VALUE(r, data, elem) \
case BOOST_PP_SEQ_ELEM(0, elem) : break;
#define DEFINE_UNIQUE_ENUM(name, values) \
enum name \
{ \
BOOST_PP_SEQ_FOR_EACH_I(EXPAND_ENUM_VALUE, \
BOOST_PP_SEQ_SIZE(values), values) \
}; \
\
namespace detail \
{ \
void UniqueEnumSanityCheck##name() \
{ \
switch (name()) \
{ \
BOOST_PP_SEQ_FOR_EACH(ADD_CASE_FOR_ENUM_VALUE, name, values) \
} \
} \
}
We can then use it like so:
DEFINE_UNIQUE_ENUM(DayOfWeek, ((Monday) (1))
((Tuesday) (2))
((Wednesday) )
((Thursday) (4)))
The enumerator value is optional; this code generates an enumeration equivalent to:
enum DayOfWeek
{
Monday = 1,
Tuesday = 2,
Wednesday,
Thursday = 4
};
It also generates a sanity-check function that contains a switch statement as described in Ben Voigt's answer. If we change the enumeration declaration such that we have non-unique enumerator values, e.g.,
DEFINE_UNIQUE_ENUM(DayOfWeek, ((Monday) (1))
((Tuesday) (2))
((Wednesday) )
((Thursday) (1)))
it will not compile (Visual C++ reports the expected error C2196: case value '1' already used).
Thanks also to Matthieu M., whose answer to another question got me interested in the Boost Preprocessor library.

I don't believe there's a way to detect this with the language itself, considering there are conceivable cases where you'd want two enumeration values to be the same. You can, however, always ensure all explicitly set items are at the top of the list:
typedef enum
{
MsgFoo1A = BASE1_VAL, // 5
MsgFoo2A = BASE2_VAL, // 7
MsgFoo1B, // 8
MsgFoo1C, // 9
MsgFoo1D, // 10
MsgFoo1E, // 11
MsgFoo2B // 12
} FOO;
So long as assigned values are at the top, no collision is possible, unless for some reason the macros expand to values which are the same.
Usually this problem is overcome by giving a fixed number of bits for each MsgFooX group, and ensuring each group does not overflow it's allotted number of bits. The "Number of bits" solution is nice because it allows a bitwise test to determine to which message group something belongs. But there's no built-in language feature to do this because there are legitimate cases for an enum having two of the same value:
typedef enum
{
gray = 4, //Gr[ae]y should be the same
grey = 4,
color = 5, //Also makes sense in some cases
couleur = 5
} FOO;

I don't know of anything that will automatically check all enum members, but if you want to check that future changes to the initializers (or the macros they rely on) don't cause collisions:
switch (0) {
case MsgFoo1A: break;
case MsgFoo1B: break;
case MsgFoo1C: break;
case MsgFoo1D: break;
case MsgFoo1E: break;
case MsgFoo2A: break;
case MsgFoo2B: break;
}
will cause a compiler error if any of the integral values is reused, and most compilers will even tell you what value (the numeric value) was a problem.

You could roll a more robust solution of defining enums using Boost.Preprocessor - wether its worth the time is a different matter.
If you are moving to C++ anyway, maybe the (proposed) Boost.Enum suits you (available via the Boost Vault).
Another approach might be to use something like gccxml (or more comfortably pygccxml) to identify candidates for manual inspection.

While we do not have full on reflection, you can solve this problem if you can relist the enumeration values.
Somewhere this is declared:
enum E { A = 0, B = 0 };
elsewhere, we build this machinery:
template<typename S, S s0, S... s>
struct first_not_same_as_rest : std::true_type {};
template<typename S, S s0, S s1, S... s>
struct first_not_same_as_rest : std::integral_constant< bool,
(s0 != s1) && first_not_same_as_rest< S, s0, s... >::value
> {};
template<typename S, S... s>
struct is_distinct : std::true_type {};
template<typename S, S s0, S... s>
struct is_distinct : std::integral_constant< bool,
std::is_distinct<S, s...>::value &&
first_not_same_as_rest< S, s0, s... >::value
> {};
Once you have that machinery (which requires C++11), we can do the following:
static_assert( is_distinct< E, A, B >::value, "duplicate values in E detected" );
and at compile time we will ensure that no two elements are equal.
This requires O(n) recursion depth and O(n^2) work by the compiler at compile time, so for extremely large enums this could cause problems. A O(lg(n)) depth and O(n lg(n)) work with a much larger constant factor can be done by sorting the list of elements first, but that is much, much more work.
With the enum reflection code proposed for C++1y-C++17, this will be doable without relisting the elements.

I didn't completely like any of the answers already posted here, but they gave me some ideas. The crucial technique is to rely on Ben Voight's answer of using a switch statement. If multiple cases in a switch share the same number, you'll get a compile error.
Most usefully to both myself and probably the original poster, this doesn't require any C++ features.
To clean things up, I used aaronps's answer at How can I avoid repeating myself when creating a C++ enum and a dependent data structure?
First, define this in some header someplace:
#define DEFINE_ENUM_VALUE(name, value) name=value,
#define CHECK_ENUM_VALUE(name, value) case name:
#define DEFINE_ENUM(enum_name, enum_values) \
typedef enum { enum_values(DEFINE_ENUM_VALUE) } enum_name;
#define CHECK_ENUM(enum_name, enum_values) \
void enum_name ## _test (void) { switch(0) { enum_values(CHECK_ENUM_VALUE); } }
Now, whenever you need to have an enumeration:
#define COLOR_VALUES(GEN) \
GEN(Red, 1) \
GEN(Green, 2) \
GEN(Blue, 2)
Finally, these lines are required to actually make the enumeration:
DEFINE_ENUM(Color, COLOR_VALUES)
CHECK_ENUM(Color, COLOR_VALUES)
DEFINE_ENUM makes the enum data type itself. CHECK_ENUM makes a test function that switches on all the enum values. The compiler will crash when compiling CHECK_ENUM if you have duplicates.

Here's a solution using X macro without Boost. First define the X macro and its helper macros. I'm using this solution to portably make 2 overloads for the X macro so that you can define the enum with or without an explicit value. If you're using GCC or Clang then it can be made shorter
#define COUNT_X_ARGS_IMPL2(_1, _2, count, ...) count
#define COUNT_X_ARGS_IMPL(args) COUNT_X_ARGS_IMPL2 args
#define COUNT_X_ARGS(...) COUNT_X_ARGS_IMPL((__VA_ARGS__, 2, 1, 0))
/* Pick the right X macro to invoke. */
#define X_CHOOSE_HELPER2(count) X##count
#define X_CHOOSE_HELPER1(count) X_CHOOSE_HELPER2(count)
#define X_CHOOSE_HELPER(count) X_CHOOSE_HELPER1(count)
/* The actual macro. */
#define X_GLUE(x, y) x y
#define X(...) X_GLUE(X_CHOOSE_HELPER(COUNT_X_ARGS(__VA_ARGS__)), (__VA_ARGS__))
Then define the macro and check it
#define BASE1_VAL (5)
#define BASE2_VAL (7)
// Enum values
#define MY_ENUM \
X(MsgFoo1A, BASE1_VAL) \
X(MsgFoo1B) \
X(MsgFoo1C) \
X(MsgFoo1D) \
X(MsgFoo1E) \
X(MsgFoo2A, BASE2_VAL) \
X(MsgFoo2B)
// Define the enum
#define X1(enum_name) enum_name,
#define X2(enum_name, enum_value) enum_name = enum_value,
enum foo
{
MY_ENUM
};
#undef X1
#undef X2
// Check duplicates
#define X1(enum_name) case enum_name: break;
#define X2(enum_name, enum_value) case enum_name: break;
static void check_enum_duplicate()
{
switch(0)
{
MY_ENUM
}
}
#undef X1
#undef X2
Use it
int main()
{
// Do something with the whole enum
#define X1(enum_name) printf("%s = %d\n", #enum_name, enum_name);
#define X2(enum_name, enum_value) printf("%s = %d\n", #enum_name, enum_value);
// Print the whole enum
MY_ENUM
#undef X1
#undef X2
}

Related

C macro parameter test at design time

I need a macro variable check at design time (preprocesor), more specific that number to fit in 24 bits.
The macro is intended to be used in a if() statement so I have no idea how to test it.
This is a ARM systick timer (24 bits) and so many time I forgot to #define the right value, especially when change the MCU clock and of course, my if() never fired and this silly mistake was hard to debug.
So in this example, there is a trick to force gcc to ERROR when PARAMETER > 24 bits ?
#define PARAMETER 20000000 // over 24 bits, should throw a error at design time
#define MyMacro(var, par) (var > par)
uint32_t variable;
if(MyMacro(variable,PARAMETER))
{
// do something
// do something WRONG because PARAMETER > 24 bits
// Actually this is working as expected, test for < is valid because
// _Static_assert() is check for TRUE condition
// But I am still trying to find a way to combine this in original macro
_Static_assert(PARAMETER < 0xFFFFFF, "Ooopss... ERROR");
}
Thanks in advance!
Unfortunately, _Static_assert is syntactically defined as a declaration, which means you can't use it directly inside of an expression.
However, _Static_assert isn't needed anyway, because you can perfectly (sans the nice compile time error reporting--but you're a programmer, you should be able to figure out a compile time failure a slightly more technical compile-time error message) emulate it with
#define static_assert_0expr(Truth) ((int)(0*sizeof(struct { int _ : (Truth)?1:-1; })))
(or an equivalent) and that you can fit in an expression (even an integer constant expression) no problem:
#define static_assert_0expr(Truth) ((int)(0*sizeof(struct { int _ : (Truth)?1:-1; })))
#define PARAMETER 20000000 // over 24 bits, should throw a error at design time
#define MyMacro(var, par) (static_assert_0expr((par)<0xffffff) + ((var) > (par)))
//or this, but this is won't preserve integer-constant expressions because of the comma:
/*#define MyMacro(var, par) (static_assert_0expr((par)<0xffffff), ((var) > (par)))*/
//alternatively: (static_assert_0expr(assertion) ? (expr) : (expr)) is the most
//general form (though it leads to larger preprocessor expansions, which may worsen debugging experience with cc -E)
#include <stdint.h>
int main()
{
static_assert_0expr(1)+1;
uint32_t variable;
if(MyMacro(variable,PARAMETER))
{
}
}
The above static_assert_0expr macro could also be implemented with _Static_assert:
#define static_assert_0expr(Truth) \
((int)(0*sizeof(struct { int _; _Static_assert(Truth,""); })))
or you could paste the body of this directly in MyMacro and customize the message (but I consider _Static_assert and its custom compile-time error message feature an unnecessary addition to C and prefer not to use it).
Well, I don't want to reply my own answer, but I think I found a solution that is working (thanks #PSkoicik) and thanks to GCC that allows statement expressions (found in this reply)
Using and returning output in C macro
So basically I could use _Static_assert() inside if() statement, with a helper macro
#define CheckParameter(val) ({bool retval = true; _Static_assert((val)< 0xFFFFFF, "Timer value too large!"); retval;})
Now my macro become
#define MyMacro(var, par) ((var > par) && CheckParameter(par))
Which should work because CheckParameter() will always return TRUE at RUNTIME but at COMPILE time, _Static_assert() will catch my error parameter.
So now I can use
if(MyMacro(variable,PARAMETER))
{
// PAREMETER will be in range
}
Hope I'm not missing something :)
If you need to check that PARAMETER is > 24 bits during compile time you can simply do this:
#define PARAMETER 20000 // over 24 bits, should throw a error at design time
...
#if PARAMETER > (1<<24)
#error PARAMETER > 24 bits
#endif
What you do here is not compile time checking but run time checking:
if(MyMacro(variable,PARAMETER))
{
// do something
// do something WRONG because PARAMETER > 24 bits
}
but what is variable doing here anyway if you just want to know if PARAMETER is > 24 bits?

compile-time struct size check, error out if odd

Is there any possible way to make the compiler bail out if the sizeof (struct Astruct) is uneven?
Background information:
We have a 16-bit microprocessor which will give processor alignment errors if a 16-bit value is mis-aligned. That might happen in the following scenario:
typedef struct
{
U8BIT u8BitValue1;
U8BIT u8BitValue2;
U8BIT u8BitValue3;
} unevenAmountOf8BitValues;
typedef struct
{
U16BIT u16BitValue1;
U16BIT u16BitValue2;
} my16BitValues;
#define U8BIT_COUNT 3
#define U16BIT_COUNT 2
typedef struct
{
unevenAmountOf8BitValues u8BitValues;
my16BitValues u16BitValues;
} valuesCombined;
typedef union
{
valuesCombined myValues;
U8BIT buffer[sizeof(valuesCombined)];
struct
{
U8BIT bufferU8[U8BIT_COUNT];
U16BIT bufferU16[U16BIT_COUNT]; /* <<-- missalignment */
} valuesPerType;
} myValuesInRamAndRom
What we do now is counting the amount of U8BIT/U16BIT/U32BIT values (well, keeping track of the amount using excel) manually and putting that in the U(8/16/32)BIT_COUNT define and then the following:
#if U8BIT_COUNT % 2 == 1
#error The number of U8BIT parameters need to be even, add a dummy
#endif
Keeping track of the amount of U8-/U16-/U32BIT values is pretty error prone and we've had quite some moments that we were thinking "hey, it ain't working", an hour or what later, oh! Darn, forgot to adjust the amount of values define.
A preferred method would be to use the sizeof operator, however that can't be used in the error checking, which I would really like to keep.
So is there anyway to use the sizeof operator and to keep some form of error checking that the amount of U8BIT values must be even?
Combined solution by Lundin and Aaron McDaid:
#define COMPILE_TIME_ASSERT(expr) {typedef U8BIT COMP_TIME_ASSERT[((!!(expr))*2-1)];}
With a C11 compiler, use:
static_assert (sizeof(the struct) % 2 == 0,
"Misaligned");
With older compilers, you can use dirty tricks like
#define COMPILE_TIME_ASSERT(expr) typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0];
...
COMPILE_TIME_ASSERT(sizeof(the_struct) % 2 == 0);
The real solution to your specific problem might however be to ensure that struct padding is enabled. You shouldn't get any misalignments then.
It's possible, using a trick that's also being used in the Linux kernel:
#define BUILD_BUG_OR_ZERO(e) (sizeof(struct{ int:-!!(e);}))
#define ENSURE_EVEN_SIZE(e) BUILD_BUG_OR_ZERO(sizeof(e) % 2 == 1)
struct uneven{
char a,b,c;
};
struct even{
char a,b,c,d;
};
int main(){
ENSURE_EVEN_SIZE(struct even);
/* compiler error: */
ENSURE_EVEN_SIZE(struct uneven);
}
If sizeof(e) % 2 == 1 is true, the bitfield int:-!!(e) would have a negative size, which is forbidden. (Ideone)
Here is the version which allows using same assertion macro multiple times in the same
file.
/*
General purpose static assert.
Works in/out -side of scope:
STATIC_ASSERT(sizeof(long)==8);
int main()
{
STATIC_ASSERT(sizeof(int)==4);
}
*/
#define STATIC_ASSERT(X) STATIC_ASSERT2(X,__LINE__)
/*
These macros are required by STATIC_ASSERT to make token pasting work.
Not really useful by themselves.
*/
#define STATIC_ASSERT2(X,L) STATIC_ASSERT3(X,L)
#define STATIC_ASSERT3(X,L) STATIC_ASSERT_MSG(X,at_line_##L)
/*
Static assertion with special error message.
Note: It depends on compiler whether message is visible or not!
STATIC_ASSERT_MSG(sizeof(long)==8, long_is_not_eight_bytes);
*/
#define STATIC_ASSERT_MSG(COND,MSG) \
typedef char static_assertion_##MSG[(!!(COND))*2-1]

Best way to define offsets via C preprocessor

I would like to define a macro that will help me to auto generate offsets. Something like this:
#define MEM_OFFSET(name, size) ...
MEM_OFFSET(param1, 1);
MEM_OFFSET(param2, 2);
MEM_OFFSET(param3, 4);
MEM_OFFSET(param4, 1);
should generate the following code:
const int param1_offset = 0;
const int param2_offset = 1;
const int param3_offset = 3;
const int param4_offset = 7;
or
enum {
param1_offset = 0,
param2_offset = 1,
param3_offset = 3,
param4_offset = 7,
}
or even (not possible using C-preprocessor only for sure, but who knows ;)
#define param1_offset 0
#define param2_offset 1
#define param3_offset 3
#define param4_offset 7
Is it possible to do without running external awk/bash/... scripts?
I'm using Keil C51
It seems I've found a solution with enum:
#define MEM_OFFSET(name, size) \
name ## _offset, \
___tmp__ ## name = name ## _offset + size - 1, // allocate right bound offset and introduce a gap to force compiler to use next available offset
enum {
MEM_OFFSET(param1, 1)
MEM_OFFSET(param2, 2)
MEM_OFFSET(param3, 4)
MEM_OFFSET(param4, 1)
};
In the comments to your post you mention that you're managing an EEPROM memory map, so this answer relates to managing memory offsets rather than answering your specific question.
One way to manage EEPROM memory is with the use of a packed struct. ie, one where there is no space between each of the elements. The struct is never instantiated, it is only used for offset calculations.
typedef struct {
uint8_t param1;
#ifdef FEATURE_ENABLED
uint16_t param2;
#endif
uint8_t param3;
} __packed eeprom_memory_layout_t;
You could then use code like the following to determine the offset of each element as needed(untested). This uses the offsetof stddef macro.
uint16_t read_param3(void) {
uint8_t buf;
eeprom_memory_layout_t * ee;
/* eeprom_read(offset, size, buf) */
eeprom_read(offsetof(eeprom_memory_layout_t, param3), sizeof(ee->param3), &buf);
return buf;
}
Note that the struct is never instantiated. Using a struct like this makes it easy to see your memory map at a glance, and macros can easily be used to abstract away the calls to offsetof and sizeof during access.
If you want to create several structures based on some preprocessor declarations, you could do something like:
#define OFFSET_FOREACH(MODIFIER) \
MODIFIER(1) \
MODIFIER(2) \
MODIFIER(3) \
MODIFIER(4)
#define OFFSET_MODIFIER_ENUM(NUM) param##NUM##_offset,
enum
{
OFFSET_FOREACH(OFFSET_MODIFIER_ENUM)
};
The preprocessor would then produce the following code:
enum
{
param1_offset,
param2_offset,
param3_offset,
param4_offset,
}
I'm sure somebody will figure a nice preprocessor trick to compute the offset values with the sum of its predecessors :)
If you are doing this in C code, you have to keep in mind that const int declarations do not declare constants in C. To declare a named constant you have to use either enum or #define.
If you need int constants specifically, then enum will work well, although I the auto-generation part might be tricky in any case. Off the top of my head I can only come up with something as ugly as
#define MEM_OFFSET_BEGIN(name, size)\
enum {\
name##_OFFSET = 0,\
name##_SIZE__ = size,
#define MEM_OFFSET(name, size, prev_name)\
name##_OFFSET = prev_name##_OFFSET + prev_name##_SIZE__,\
name##_SIZE__ = size,
#define MEM_OFFSET_END()\
};
and then
MEM_OFFSET_BEGIN(param1, 1)
MEM_OFFSET(param2, 2, param1)
MEM_OFFSET(param3, 4, param2)
MEM_OFFSET(param4, 1, param3)
MEM_OFFSET_END()
Needless to say, the fact that it requires the next offset declaration to refer to the previous offset declaration by name defeats most of the purpose of this construct.
Try something like:
#define OFFSET(x) offsetof(struct {\
char param1[1], param2[2], param3[4], param4[1];\
},x)
Then you can use OFFSET(param1), etc. and it's even an integer constant expression.

Calculating parity bit with the preprocessor (parity functional style with call by ref)

Consider I want to generate parities at compile time. The parity calculation is given literal constants and with any decent optimizer it will boil down to a single constant itself. Now look at the following parity calculation with the C preprocessor:
#define PARITY16(u16) (PARITY8((u16)&0xff) ^ PARITY8((u16)>>8))
#define PARITY8(u8) (PARITY4((u8)&0x0f) ^ PARITY4((u8)>>4))
#define PARITY4(u4) (PARITY2((u4)&0x03) ^ PARITY2((u4)>>2))
#define PARITY2(u2) (PARITY1((u2)&0x01) ^ PARITY1((u2)>>1))
#define PARITY1(u1) (u1)
int message[] = { 0x1234, 0x5678, PARITY16(0x1234^0x5678));
This will calculate the parity at compile time, but it will produce an enormous amount of intermediate code, expanding to 16 instances of the expression u16 which itself can be e.g. an arbitrary complex expression. The problem is that the C preprocessor can't evaluate intermediary expressions and in the general case only expands text (you can force it to do integer arithmetic in-situ but only for trivial cases, or with gigabytes of #defines).
I have found that the parity for 3 bits can be generated at once by an arithmetic expression: ([0..7]*3+1)/4. This reduces the 16-bit parity to the following macro:
#define PARITY16(u16) ((4 & ((((u16)&7)*3+1) ^ \
((((u16)>>3)&7)*3+1) ^ \
((((u16)>>6)&7)*3+1) ^ \
((((u16)>>9)&7)*3+1) ^ \
((((u16)>>12)&7)*3+1) ^ \
((((u16)>>15)&1)*3+1))) >> 2))
which expands u16only 6 times. Is there an even cheaper (in terms of number of expansions) way, e.g. a direct formula for a 4,5,etc. bit parity? I couldn't find a solution for a linear expression of the form (x*k+d)/m for acceptable (non-overflowing) values k,d,m for a range > 3 bits. Anyone out there with a more clever shortcut for preprocessor parity calculation?
Is something like this what you are looking for?
The following "PARITY16(u16)" preprocessor macro can be used as a literal constant in structure assignments, and it only evaluates the argument once.
/* parity.c
* test code to test out bit-twiddling cleverness
* 2013-05-12: David Cary started.
*/
// works for all 0...0xFFFF
// and only evalutes u16 one time.
#define PARITYodd33(u33) \
( \
((((((((((((((( \
(u33) \
&0x555555555)*5)>>2) \
&0x111111111)*0x11)>>4) \
&0x101010101)*0x101)>>8) \
&0x100010001)*0x10001)>>16) \
&0x100000001)*0x100000001)>>32) \
&1)
#define PARITY16(u16) PARITYodd33(((unsigned long long)u16)*0x20001)
// works for all 0...0xFFFF
// but, alas, generates 16 instances of u16.
#define PARITY_16(u16) (PARITY8((u16)&0xff) ^ PARITY8((u16)>>8))
#define PARITY8(u8) (PARITY4((u8)&0x0f) ^ PARITY4((u8)>>4))
#define PARITY4(u4) (PARITY2((u4)&0x03) ^ PARITY2((u4)>>2))
#define PARITY2(u2) (PARITY1((u2)&0x01) ^ PARITY1((u2)>>1))
#define PARITY1(u1) (u1)
int message1[] = { 0x1234, 0x5678, PARITY16(0x1234^0x5678) };
int message2[] = { 0x1234, 0x5678, PARITY_16(0x1234^0x5678) };
#include <stdio.h>
int main(void){
int errors = 0;
int i=0;
printf(" Testing parity ...\n");
printf(" 0x%x = message with PARITY16\n", message1[2] );
printf(" 0x%x = message with PARITY_16\n", message2[2] );
for(i=0; i<0x10000; i++){
int left = PARITY_16(i);
int right = PARITY16(i);
if( left != right ){
printf(" 0x%x: (%d != %d)\n", i, left, right );
errors++;
return 0;
};
};
printf(" 0x%x errors detected. \n", errors );
} /* vim: set shiftwidth=4 expandtab ignorecase : */
Much like the original code you posted, it pairs up bits and (in effect) calculates the XOR between each pair, then from the results it pairs up the bits again, halving the number of bits each time until only a single parity bit remains.
But is that really what you wanted ?
Many people say they are calculating "the parity" of a message.
But in my experience, most of the time they are really generating
a error-detection code bigger than a single parity bit --
a LRC, or a CRC, or a Hamming code, or etc.
further details
If the current system is compiling in a reasonable amount of time,
and it's giving the correct answers, I would leave it alone.
Refactoring "how the pre-processor generates some constant"
will produce bit-for-bit identically the same runtime executable.
I'd rather have easy-to-read source
even if it takes a full second longer to compile.
Many people use a language easier-to-read than the standard C preprocessor to generate C source code.
See pycrc, the character set extractor, "using Python to generate C", etc.
If the current system is taking way too long to compile,
rather than tweak the C preprocessor,
I would be tempted to put that message, including the parity, in a separate ".h" file
with hard-coded constants (rather than force the C pre-processor to calculate them every time),
and "#include" that ".h" file in the ".c" file for the embedded system.
Then I would make a completely separate program (perhaps in C or Python)
that does the parity calculations and
prints out the contents of that ".h" file as pre-calculated C source code,
something like
print("int message[] = { 0x%x, 0x%x, 0x%x };\n",
M[0], M[1], parity( M[0]^M[1] ) );
and tweak my MAKEFILE to run that Python (or whatever) program to regenerate that ".h" file
if, and only if, it is necessary.
As mfontanini says, an inline function is much better.
If you insist on a macro, you can define a temporary variable.
With gcc, you can do it and still have the macro which behaves as an expression:
#define PARITY(x) ({int tmp=x; PARITY16(tmp);})
If you want to stick to the standard, you have to make the macro a statement:
#define PARITY(x, target) do { int tmp=x; target=PARITY16(tmp); } while(0).
In both cases, you can have ugly bugs if tmp ends up a name used in the function (even worse - used within the parameter passed to the macro).

c macro for setting bits

I have a program that compares variables from two structs and sets a bit accordingly for a bitmap variable. I have to compare each variables of the struct. No. of variables in reality are more for each struct but for simplicity I took 3. I wanted to know if i can create a macro for comparing the variables and setting the bit in the bitmap accordingly.
#include<stdio.h>
struct num
{
int a;
int b;
int c;
};
struct num1
{
int d;
int e;
int f;
};
enum type
{
val1 = 0,
val2 = 1,
val3 = 2,
};
int main()
{
struct num obj1;
struct num1 obj2;
int bitmap = 0;
if( obj1.a != obj2.d)
{
bitmap = bitmap | val1;
}
if (obj1.b != obj2.e)
bitmap = bitmap | val2;
printf("bitmap - %d",bitmap);
return 1;
}
can i declare a macro like...
#define CHECK(cond)
if (!(cond))
printf(" failed check at %x: %s",__LINE__, #cond);
//set the bit accordingly
#undef CHECK
With a modicum of care, you can do it fairly easily. You just need to identify what you're comparing and setting carefully, and pass them as macro parameters. Example usage:
CHECK(obj1.a, obj2.d, bitmap, val1);
CHECK(obj1.b, obj2.e, bitmap, val2);
This assumes that CHECK is defined something like:
#define STRINGIFY(expr) #expr
#define CHECK(v1, v2, bitmap, bit) do \
{ if ((v1) != (v2)) \
{ printf("failed check at %d: %s\n", __LINE__, STRINGIFY(v1 != v2)); \
(bitmap) |= (1 << (bit)); \
} \
} while (0)
You can lay the macro out however you like, of course; I'm not entirely happy with that, but it isn't too awful.
Demo Code
Compilation and test run:
$ gcc -Wall -Wextra -g -O3 -std=c99 xx.c -o xx && ./xx
failed check at 40: obj1.a != obj2.d
failed check at 42: obj1.c != obj2.f
bitmap - 5
$
Actual code:
#include <stdio.h>
struct num
{
int a;
int b;
int c;
};
struct num1
{
int d;
int e;
int f;
};
enum type
{
val1 = 0,
val2 = 1,
val3 = 2,
};
#define STRINGIFY(expr) #expr
#define CHECK(v1, v2, bitmap, bit) do \
{ if ((v1) != (v2)) \
{ printf("failed check at %d: %s\n", __LINE__, STRINGIFY(v1 != v2)); \
(bitmap) |= (1 << (bit)); \
} \
} while (0)
int main(void)
{
struct num obj1 = { 1, 2, 3 };
struct num1 obj2 = { 2, 2, 4 };
int bitmap = 0;
CHECK(obj1.a, obj2.d, bitmap, val1);
CHECK(obj1.b, obj2.e, bitmap, val2);
CHECK(obj1.c, obj2.f, bitmap, val3);
printf("bitmap - %X\n", bitmap);
return 0;
}
Clearly, this code relies on you matching the right elements and bit numbers in the invocations of the CHECK macro.
It's possible to devise more complex schemes using offsetof() etc and initialized arrays describing the data structures, etc, but you'd end up with a more complex system and little benefit. In particular, the invocations can't reduce the parameter count much. You could assume 'bitmap' is the variable. You need to identify the two objects, so you'll specify 'obj1' and 'obj2'. Somewhere along the line, you need to identify which fields are being compared and the bit to set. That could be some single value (maybe the bit number), but you've still got 3 arguments (CHECK(obj1, obj2, valN) and the assumption about bitmap) or 4 arguments (CHECK(obj1, obj2, bitmap, valN) without the assumption about bitmap), but a lot of background complexity and probably a greater chance of getting it wrong. If you can tinker with the code so that you have a single type instead of two types, etc, then you can make life easier with the hypothetical system, but it is still simpler to handle things the way shown in the working code, I think.
I concur with gbulmer that I probably wouldn't do things this way, but you did state that you had reduced the sizes of the structures dramatically (for which, thanks!) and it would become more enticing as the number of fields increases (but I'd only write out the comparisons for one pair of structure types once, in a single function).
You could also revise the macro to:
#define CHECK(cond, bitmap, bit) do \
{ if (cond) \
{ printf("failed check at %d: %s\n", __LINE__, STRINGIFY(cond)); \
(bitmap) |= (1 << (bit)); \
} \
} while (0)
CHECK(obj1.a != obj2.d, bitmap, val1);
...
CHECK((strcmp(obj3.str1, obj4.str) != 0), bitmap, val6);
where the last line shows that this would allow you to choose arbitrary comparisons, even if they contain commas. Note the extra set of parentheses surrounding the call to strcmp()!
You should be able to do that except you need to use backslash for multi-line macros
#ifndef CHECK
#define CHECK(cond) \
if (!(cond)) { \
printf(" failed check at %x: %s",__LINE__, #cond); \
//set the bit accordingly
}
#endif /* CHECK */
If you want to get really fancy (and terse), you can use the concatenation operator. I also recommend changing your structures around a little bit to have different naming conventions, though without knowing what you're trying to do with it, it's hard to say. I also noticed in your bit field that you have one value that's 0; that won't tell you much when you try to look at that bit value. If you OR 0 into anything, it remains unchanged. Anyway, here's your program slightly re-written:
struct num {
int x1; // formerly a/d
int x2; // formerly b/e
int x3; // formerly c/f
};
enum type {
val1 = 1, // formerly 0
val2 = 2, // formerly 1
val3 = 4, // formerly 2
};
// CHECK uses the catenation operator (##) to construct obj1.x1, obj1.x2, etc.
#define CHECK(__num) {\
if( obj1.x##__num != obj2.x##__num )\
bitmap |= val##__num;\
}
void main( int argc, char** argv ) {
struct num obj1;
struct num obj2;
int bitmap = 0;
CHECK(1);
CHECK(2);
CHECK(3);
}
As a reasonable rule of thumb, when trying to do bit-arrays is C, there needs to be a number that can be used to index the bit.
You can either pass that bit number into the macro, or try to derive it.
Pretty much the only thing available at compile time or run time is the address of a field.
So you could use that.
There are a few questions to understand if it might work.
For your structs:
Are all the fields in the same order? I.e. you can compare c with f, and not c with e?
Do all of the corresponding fields have the same type
Is the condition just equality? Each macro will have the condition wired in, so each condition needs a new macro.
If the answer to all is yes, then you could use the address:
#define CHECK(s1, f1, s2, f2) do \
{ if ((&s1.f1-&s1 != &s2.f2-&s2) || (sizeof(s1.f1)!=sizeof(s2.f2)) \
|| (s1.f1) != (s2.f2) \
{ printf("failed check at %d: ", #s1 "." #f1 "!=" #s1 "." #f1 "\n", \
__LINE__); \
(shared_bitmap) |= (1 << (&s1.f1-&s1)); // test failed \
} \
} while (0)
I'm not too clear on whether it is a bitmap for all comparisons, or one per struct pair. I've assumed it is a bit map for all.
There is quite a lot of checking to ensure you haven't broken 'the two rules':
(&s1.f1-&s1 != &s2.f2-&s2) || (sizeof(s1.f1)!=sizeof(s2.f2))
If you are confident that the tests will be correct, without those constraints, just throw that part of the test away.
WARNING I have not compiled that code.
This becomes much simpler if the values are an array.
I probably wouldn't use it. It seems a bit too tricky to me :-)

Resources