Macro for run-once conditioning - c

I am trying to build a macro that runs a code only once.
Very useful for example if you loop a code and want something inside to happen only once. The easy to use method:
static int checksum;
for( ; ; )
{
if(checksum == 0) { checksum == 1; // ... }
}
But it is a bit wasteful and confusing. So I have this macros that use checking bits instead of checking true/false state of a variable:
#define CHECKSUM(d) static d checksum_boolean
#define CHECKSUM_IF(x) if( ~(checksum_boolean >> x) & 1) \
{ \
checksum_boolean |= 1 << x;
#define CHECKSUM_END }1
The 1 at the end is to force the user to put semi-colon at the end. In my compiler this is allowed.
The problem is figuring out how to do this without having the user to specify x (n bit to be checked).
So he can use this:
CHECKSUM(char); // 7 run-once codes can be used
for( ; ; )
{
CHECKSUM_IF
// code..
CHECKSUM_END;
}
Ideas how can I achieve this?

I guess you're saying you want the macro to somehow automatically track which bit of your bitmask contains the flag for the current test. You could do it like this:
#define CHECKSUM(d) static d checksum_boolean; \
d checksum_mask
#define CHECKSUM_START do { checksum_mask = 1; } while (0)
#define CHECKSUM_IF do { \
if (!(checksum_boolean & checksum_mask)) { \
checksum_boolean |= checksum_mask;
#define CHECKSUM_END \
} \
checksum_mask <<= 1; \
} while (0)
#define CHECKSUM_RESET(i) do { checksum_boolean &= ~((uintmax_t) 1 << (i)); } while (0)
Which you might use like this:
CHECKSUM(char); // 7 run-once codes can be used
for( ; ; )
{
CHECKSUM_START;
CHECKSUM_IF
// code..
CHECKSUM_END;
CHECKSUM_IF
// other code..
CHECKSUM_END;
}
Note, however, that that has severe limitations:
The CHECKSUM_START macro and all the corresponding CHECKSUM_IF macros must all appear in the same scope
Control must always pass through CHECKSUM_START before any of the CHECKSUM_IF blocks
Control must always reach the CHECKSUM_IF blocks in the same order. It may only skip a CHECKSUM_IF block if it also skips all subsequent ones that use the same checksum bitmask.
Those constraints arise because the preprocessor cannot count.
To put it another way, barring macro redefinitions, a macro without any arguments always expands to exactly the same text. Therefore, if you don't use a macro argument to indicate which flag bit applies in each case then that needs to be tracked at run time.

Related

Using ENUMs as bitmaps, how to validate in C

I am developing firmware for an embedded application with memory constraints. I have a set of commands that need to processed as they are received. Each command falls under different 'buckets' and each 'bucket' gets a range of valid command numbers. I created two ENUMs as shown below to achieve this.
enum
{
BUCKET_1 = 0x100, // Range of 0x100 to 0x1FF
BUCKET_2 = 0x200, // Range of 0x200 to 0x2FF
BUCKET_3 = 0x300, // Range of 0x300 to 0x3FF
...
...
BUCKET_N = 0xN00 // Range of 0xN00 to 0xNFF
} cmd_buckets;
enum
{
//BUCKET_1 commands
CMD_BUCKET_1_START = BUCKET_1,
BUCKET_1_CMD_1,
BUCKET_1_CMD_2,
BUCKET_1_CMD_3,
BUCKET_1_CMD_4,
//Add new commands above this line
BUCKET_1_CMD_MAX,
//BUCKET_2 commands
CMD_BUCKET_2_START = BUCKET_2,
BUCKET_2_CMD_1,
BUCKET_2_CMD_2,
BUCKET_2_CMD_3,
//Add new commands above this line
BUCKET_2_CMD_MAX,
//BUCKET_3 commands
...
...
...
//BUCKET_N commands
CMD_BUCKET_N_START = BUCKET_N
BUCKET_N_CMD_1,
BUCKET_N_CMD_2,
BUCKET_N_CMD_3,
BUCKET_N_CMD_4,
//Add new commands above this line
BUCKET_N_CMD_MAX,
}cmd_codes
When my command handler function receives a command code, it needs to check if the command is enabled before processing it. I plan to use a bitmap for this. Commands can be enabled or disabled from processing during run-time. I can use an int for each group (giving me 32 commands per group, I realize that 0xN00 to 0xN20 are valid command codes and that others codes in the range are wasted). Even though commands codes are wasted, the design choice has the benefit of easily telling the group of the command code when seeing raw data on a console.
Since many developers can add commands to the 'cmd_codes' enum (even new buckets may be added as needed to the 'cmd_buckets' enum), I want to make sure that the number of command codes in each bucket does not exceed 32 (bitmap is int). I want to catch this at compile time rather than run time. Other than checking each BUCKET_N_CMD_MAX value as below and throwing a compile time error, is there a better solution?
#if (BUCKET_1_CMD_MAX > 0x20)
#error ("Number of commands in BUCKET_1 exceeded 32")
#endif
#if (BUCKET_2_CMD_MAX > 0x20)
#error ("Number of commands in BUCKET_2 exceeded 32")
#endif
#if (BUCKET_3_CMD_MAX > 0x20)
#error ("Number of commands in BUCKET_3 exceeded 32")
#endif
...
...
...
#if (BUCKET_N_CMD_MAX > 0x20)
#error ("Number of commands in BUCKET_N exceeded 32")
#endif
Please also suggest if there is a more elegant way to design this.
Thanks, I appreciate your time and patience.
First fix the bug in the code. As mentioned in comments, you have a constant BUCKET_1 = 0x100 which you then assign CMD_BUCKET_1_START = BUCKET_1. The trailing enums will therefore get values 0x101, 0x102, ... and BUCKET_1_CMD_MAX will be 0x106. Since 0x106 is always larger than 0x20, your static assert will always trigger.
Fix that so that it actually checks the total number of items in the enum instead, like this:
#define BUCKET_1_CMD_N (BUCKET_1_CMD_MAX - CMD_BUCKET_1_START)
#define BUCKET_2_CMD_N (BUCKET_2_CMD_MAX - CMD_BUCKET_2_START)
...
Assuming the above is fixed, then you can replace the numerous checks with a single macro. Not a great improvement, but at least it reduces code repetition:
#define BUCKET_MAX 32 // use a defined constant instead of a magic number
// some helper macros:
#define CHECK(n) BUCKET_ ## n ## _CMD_N
#define STRINGIFY(n) #n
// the actual macro:
#define BUCKET_CHECK(n) \
_Static_assert(CHECK(n) <= BUCKET_MAX, \
"Number of commands in BUCKET_" STRINGIFY(n) "_CMD_N exceeds BUCKET_MAX.");
// usage:
int main (void)
{
BUCKET_CHECK(1);
BUCKET_CHECK(2);
}
Output from gcc in case one constant is too large:
error: static assertion failed: "Number of commands in BUCKET_1_CMD_N exceeds BUCKET_MAX."
note: in expansion of macro 'BUCKET_CHECK'
EDIT
If combining the bug fix with the check macro, you would get this:
#define BUCKET_MAX 32
#define CHECK(n) (BUCKET_##n##_CMD_MAX - CMD_BUCKET_##n##_START)
#define STRINGIFY(n) #n
#define BUCKET_CHECK(n) \
_Static_assert(CHECK(n) <= BUCKET_MAX, \
"Number of commands in BUCKET " STRINGIFY(n) " exceeds BUCKET_MAX.");
int main (void)
{
BUCKET_CHECK(1);
BUCKET_CHECK(2);
}
First of all, preprocessor commands do not work that way. The C preprocessor is able to "see" only names instruced by the #define statement or passes as compiler flags. It is not able to see constants defined as part of an enum or with the const keyword. You should use _Static_assert to validate the commands instead of the preprocessor.
As for the commands, I would suggest to have all the commands numbered in the range 0..0x20:
enum {
BUCKET_1_CMD_1,
BUCKET_1_CMD_2,
...
BUCKET_1_CMD_MAX,
};
enum {
BUCKET_2_CMD_1,
BUCKET_2_CMD_2,
...
BUCKET_2_CMD_MAX,
};
Then you need only a single guard value to check if all the commands are in valid range:
#define MAX_COMMAND 0x20
_Static_assert(BUCKET_1_CMD_MAX <= MAX_COMMAND, "too many bucket 1 commands");
_Static_assert(BUCKET_2_CMD_MAX <= MAX_COMMAND, "too many bucket 2 commands");
To use the commands, bitwise-or them together with the bucket "offset":
enum {
BUCKET_1 = 0x100,
BUCKET_2 = 0x200,
};
...
int cmd = BUCKET_2 | BUCKET_2_CMD_1;

C macros: Conditional code based on parameter value?

Is there a cleaner/simpler way to do this?
The below works OK, but I think it's ugly - I'd like a solution that doesn't need a separate #define for every possible invalid value passed as "port".
#define _port_A_config_digital(mask) // do nothing; this port is always digital
#define _port_B_config_digital(mask) AD1PCFGSET = (mask)
#define _port_C_config_digital(mask)
#define _port_D_config_digital(mask)
#define _port_E_config_digital(mask)
#define _port_F_config_digital(mask)
#define _port_G_config_digital(mask)
#define _port_H_config_digital(mask)
#define _port_I_config_digital(mask)
#define _port_J_config_digital(mask)
#define _port_K_config_digital(mask)
#define ConfigDigitalBits(port, mask) _port_##port##_config_digital(mask)
If "port" is anything other than B, I want a null statement.
I'd like to get rid of all the #defines other than the one that does something.
I want to do this because on this MCU all ports other than B are always digital and there's nothing to be done.
But calling ConfigDigitalBits() ought to be a valid thing to do for any port.
You could do something like
#define CONFIG_DIGITAL_BITS(PORT, MASK) \
do { if (PORT == 'B') AD1PCFGSET = (MASK); } while (0)
and trust (or check by reading the assembly) your compiler to evaluate the if condition at compile-time. That is,
CONFIG_DIGITAL_BITS('B', 0x42);
would generate code for only
AD1PCFGSET = 0x42;
and
CONFIG_DIGITAL_BITS('A', 0x42);
would generate no code at all.
The proposed code above has the problem that it ignores errors. For example,
CONFIG_DIGITAL_BITS('Z', 0x42);
would happily compile although there is no port Z. You could assert on this but this will only catch the error at run-time.
Once you got to this, consider getting rid of the macro at whole and use an inline function instead that will also permit constant propagation.
inline void
config_digital_bits(const char port, const unsigned mask)
{
assert(port >= 'A' && port <= 'K');
if (port == 'B')
AD1PCFGSET = mask;
}

Array in #define

I am trying to achieve something like this:
#define MACRO(x) {PORTB=0,PORTC=0,PORTD=0}
MACRO(0); //This would get replaced by PORTB=0;
MACRO(1); //PORTC=0;
MACRO(2); //PORTD=0;
I want to create a "macro array". I would pass in an index to it and it would return the right code.
Is this possible?
EDIT:
If it helps, PORTB, PORTC and PORTD are all #defines.
It can be done using the preprocessor, but it is arguably ugly.
#define MACRO_CASE0 PORTB = 0
#define MACRO_CASE1 PORTC = 0
#define MACRO_CASE2 PORTD = 0
#define MACRO(X) MACRO_CASE##X
Also have a look at the Boost.Preprocessor library. (It works for both C and C++.)
Update: After the discussion with Jonathan Leffler (see below) I feel an obligation to update the answer with an exhortation for new C programmers not to abuse the (powerful but dirty) technique shown above.
If you – as the OP requested – want to pass in an index to it and it would return the right code, then you'll need to resort to preprocessor programming. However, if all you want to do is execute different code based on some condition and want this to have no run-time overhead if the condition is a compile-time constant, then the following approach is not only much cleaner but also more flexible as it allows passing run-time values too.
/* '#include' this definition in any file where you want to use it. */
static inline void
do_the_right_thing(const int selector)
{
switch (selector)
{
case 0:
PORTB = 0;
break;
case 1:
PORTC = 0;
break;
case 2:
PORTD = 0;
break;
default:
assert(!"cannot do the right thing: invalid selector");
}
}
Now, in your code, if you write
do_the_right_thing(1); /* selector is a compile-time constant */
a decent compiler with appropriate optimizations enabled will generate no overhead compared to using a macro. However, you can also write
do_the_right_thing(rand() % 3); /* selector is a run-time expression */
and the compiler will insert some fast switching code to select the appropriate operation at run-time.
This would do the task, but it doesn't extend or generalize very gracefully:
#define MACRO(x) (((x) == 0) ? PORTB=0 : ((x) == 1) ? PORTC=0 : PORTD=0)

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 :-)

Writing a C Macro

I have to write a macro that get as parameter some variable, and for each two sequential bits with "1" value replace it with 0 bit.
For example: 10110100 will become 10000100.
And, 11110000->00000000
11100000->100000000
I'm having a troubles writing that macro. I've tried to write a macro that get wach bit and replace it if the next bit is the same (and they both 1), but it works only for 8 bits and it's very not friendly...
P.S. I need a macro because I'm learning C and this is an exercise i found and i couldn't solve it myself. i know i can use function to make it easily... but i want to know how to do it with macros.
Thanks!
#define foo(x,i) (((x) & (3<<i)) == (3<<i)) ? ((x) - (3 << i)) : (x)
#define clear_11(x) foo(foo(foo(foo(foo(foo(foo(foo(foo(x,8),7),6),5),4),3),2),1),0)
This will do the job. However the expansion is quite big and compilation may take a while. So do not try this at work ;)
#define clear_bit_pairs(_x) ((_x)&~(((_x)&((_x)>>1))*3))
#define clear_bit_pairs(_x) ((_x) ^ ((((_x)&((_x)>>1))<<1) | ((_x)&((_x)>>1))) )
This will work, but it does not pair up. If it finds the consecutive '1' it will just erase. for example 11100000 will become 00000000 because the first 111 are consecutive.
#define foo(x) ({ \
typeof(x) _y_ = x; \
for(int _i_ = 0; _i_ < (sizeof(typeof(x)) << 3) + 1; _i_++) { \
if((_y_ >> _i_ & 3) == 3) { \
_y_ &= ~(3 << _i_); \
} \
} \
_y_; \
})
This probably only works in GCC, since it uses inline statements. I haven't tested it, so it probably doesn't work at all. It is your job to make it work. :-)
The nice thing about this is that it will work with any integral type. It also doesn't rely on any external functions. The downside is that it is not portable. (And I realize that this is sort of cheating.)

Resources