I am facing a problem while making a code more general, I want to replace hardcoded values with macro but I am facing this issue :
Original code :
#define io_dir_in(port, pin) NRF_P##port->PIN_CNF[pin] = (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) + (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
io_dir_in(0, 0);
I added :
#define A_Port 0
#define A_Pin 0
And replaced :
io_dir_in(A_Port, A_Pin);
But I get the error identifer "NRF_PA_Port" is undefined because NRF_P and A_Port are getting concatenated. Anyway to make it work ?
The problem is that "concatenation of tokens" is done before an expansion of tokens. You need to add an extra step of expansion in between.
#define io_dir_in_impl(port, pin) NRF_P##port->PIN_CNF[pin] = (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) + (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
#define io_dir_in(port, pin) io_dir_in_impl(port, pin)
Now before io_dir_in_impl() is expanded all its arguments are expanded. Thus A_Port will be replaced with 0.
With this tweak io_dir_in(A_Port, A_Pin); expands as:
NRF_P0->PIN_CNF[0] = (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) + (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos);
Related
I want to make a macro to utilize two macros
#define BUZZER_ON func_buzz(1);\
flag_buzzer_on = 1;\
#define BUZZER_OFF func_buzz(0);\
flag_buzzer_on = 0;\
#define BUZZER_TOGGLE ((flag_buzzer_on == 1) ? BUZZER_OFF : BUZZER_ON ) ;
where func_buzz is function to turn buzzer on or off depending on value passed
BUZZER ON and BUZZER OFF MACRO is working correctly
but when i use MACRO BUZZER_TOGGLE i get error
expression expected : or ) before ;
How to write MACRO BUZZER_TOGGLE
remember that in your case you can think of macro expansion simplified as text replacement although that's not quite correct as #Eric Postpischil has correcty stated in his comment.
In your case the line
BUZZER_TOGGLE;
is expanded to
((flag_buzzer_on == 1) ? func_buzz(0); flag_buzzer_on = 0; : func_buzz(1); flag_buzzer_on = 1;) ;;
(assuming the second #define BUZZER_ON in the question is a typo for BUZZER_OFF).
You can see that this is no valid statement.
You could make it valid if you defined
#define BUZZER_ON (func_buzz(1), flag_buzzer_on = 1)
and BUZZER_OFF accordingly
but maybe it's easier just to use simple functions instead of macros.
This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 2 years ago.
I'm looking through this project klib, and in one of the files (kseq.h, 75-77), there is macros this function:
#ifndef kroundup32
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
#endif
How does this function work? Does it return 7 things? I have an idea of the basic operations inside, I just don't get what is the form of its operation or output.
Normally you'd define this as a function and let the compiler figure out the rest, but if you're implementing it as a macro you need to consider the context.
Remember macros get expanded in the source, so they need to be syntactically valid in the context they appear. Within a function call you can't use ;, so , is used instead as a substitute.
Like this function might be called:
int v = 5 + 3 << 2;
if (other_fn(kroundup(v)) { ... }
Where using ; there would obviously break things badly. It needs ,:
if (other_fn((--(v), (v)|=(v)>>1, (v)|=(v)>>2, (v)|=(v)>>4, (v)|=(v)>>8, (v)|=(v)>>16, ++(v))) { ... }
Now the (x) part is a tradition to handle complex expressions:
if (other_fn(kroundup(5 + 3 << 2)) { ... }
Yet it doesn't handle those correctly due to using operators like -- that make no sense on anything but variables:
if (other_fn((--(5 + 3 << 2), (5 + 3 << 2)|=(5 + 3 << 2)>>1, ..., ++(5 + 3 << 2))) { ... }
It should be just x in the macro to catch problems like this.
In all honesty this macro shouldn't exist, the macro is just a terrible idea because it's buggy, it impedes understanding, and you should just let the compiler inline it as a regular function it if it thinks it can, like this:
int kroundup32(x) {
--x;
x |= x>>1;
x |= x>>2;
x |= x>>4;
x |= x>>8;
x |= x>>16;
++x;
return x;
}
Where that is way more readable.
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.
I am trying to allow multiple cases to run in a switch statement. I have a bitmask as follows:
#define SHOOT_ROCKET 2 << 16
#define MOVE_FORWARD 3 << 16
Later, I do
switch (int game_action)
and I have
case SHOOT_ROCKET:
result = fire_weapon(rl);
I don't want to 'break', because I want possibility of multiple actions. But I am returning a value called 'result'. I store this as a variable and return at the end. I can tell other case: statements are running though even when they shouldn't because result keeps getting changed and doesn't if I add break;
What is the best way to deal with this?
Update: I've been told to do if instead.
I changed my << bitmasks so they start at 1 now.
I am experiencing a weird bug
if (game_action->action & SHOOT_ROCKET)
{
game_action->data=5;
}
if (game_action->action & MOVE_FORWARD)
{
game_action->data=64;
}
I am not concerned about game_action being overwritten when I intend for multiple if's to evaluate to true
However: it seems MOVE_FORWARD is happening even if I only try and shoot a rocket!
game_action is a void pointer normally, so this is how it's setup in the function:
game_action = (game_action) *game_action_ptr;
I have verified the bitmask is correct with
printf("%d", game_action->action >> 16) which prints 2.
So why is '3' (the move forward) happening when I am only trying to shoot a rocket?
Please do update your question.
So why is '3' (the move forward) happening when I am only trying to shoot a rocket?
The first thing you want to look at is
#define SHOOT_ROCKET 2 << 16
#define MOVE_FORWARD 3 << 16
and think what that evaluates to. It will evaluate to the following binary numbers (Python is handy for this kind of stuff, 0b is just a prefix that means binary is following):
>>> bin(2 << 16)
'0b100000000000000000'
>>> bin(3 << 16)
'0b110000000000000000'
So you see that you use one bit twice in your #defines (Retired Ninja already pointed this out). This means that if game_action->action is set to anything where the bit 2 << 16 is 1, both of your ifs will evaluate to true, because both #defines have that bit set to 1.
to make them mutually exclusive, should i do 2, 4, 8, instead of 1,2,3,4?
If you want to easily keep track of which bits are used, you can either use powers of two (1,2,4,8,16, etc), e.g. #define MOVE_FORWARD 4 (I'm ignoring the << 16 you have, you can add that if you want), or you can shift a 1 by a variable number of bits, both result in the same binary numbers:
#define MOVE_LEFT 1 << 0
#define MOVE_RIGHT 1 << 1
#define MOVE_UP 1 << 3
#define MOVE_DOWN 1 << 4
There are legitimate cases where bitmasks need to have more than one bit set, for example for checking if any one of several bits are set:
#define MOVE_LEFT ... (as above)
#define SHOOT_ROCKET 1 << 5
#define SHOOT_GUN 1 << 6
//...
#define ANY_MOVEMENT 0xF
#define ANY_WEAPON_USE 0xF << 4
and then check:
if (action & ANY_MOVEMENT) { ... }
if (action & ANY_WEAPON_USE) { ... }
place parens '(' ')' around the value part (2<<15) kind of values so there is no errors introduced by the text replacement.
I.E. this:
'if( (&game_action->action & MOVE_FORWARD) == MOVE_FORWARD)'
becomes
'if( (&game_action->action & 2 << 16) == 2 << 16)'
Note the posted code is missing a left paren, which I added.
Where the '&' has a higher Precedence the '<<' so it (effectively) becomes
'if( ( (&game_action->action & 2) << 16) == 2 << 16)'
where the '&' is done to the 2 and not to the 2<<16
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.)