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.
Related
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;
}
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 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)
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Cant I use if/else, if/else if/else in #define directive? Below code gives errors:
#include <stdio.h>
#define makro(a) if(a%2 == 0) 1 else 0;
int main(void) {
// your code goes here
int a = makro(5);
printf("%d\n", a);
return 0;
}
prog.c: In function ‘main’:
prog.c:3:18: error: expected expression before ‘if’
#define makro(a) if(a%2 == 0) 1 else 0;
^
prog.c:7:10: note: in expansion of macro ‘makro’
int a = makro(5);
^
Yes. That macro expands like this
int a = if(a%2 == 0) 1 else 0;
And obviously that isn't legal. You could try this (using a ternary). Also note that this bitwise and is equivalent to the modulo 2 from before.
#define makro(a) ((((a) & 1) == 0) ? 1 : 0)
of course you could shorten it a little more to
#define makro(a) (!((a) & 1))
You can see the problem if you unpick the macro:
int a = if(5 == 0) 1 else 0;
This is clearly syntatically incorrect (if... is a statement not an expression).
You can replace the if with the ternary (which is an expression):
int a = 5 == 0 ? 1 : 0;
and, reforming to the macro gives you a correct definition:
#define makro(a) ((a%2) == 0) ? 1 : 0;
I've also introduced parentheses in case a is a function, an expression like c++ etc.
Expression Statements
As a final remark, if you are using GNU C, then you could use expression statements which is a non-standard C extension. Then you get your if... statement back again. See
http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
for more details.
You should define the macro like this:
#define makro(a) do { (a%2 == 0) ? 1 : 0; } while (0)
or
#define makro(a) ((a%2 == 0) ? 1 : 0)
putting semicolomn at the end of a macro is almost always a bad idea because for example you get in trouble writing:
printf( "Val %d", makro(a) );
if you put the semicolomn
This macro can be better defined as:
#define makro(a) ((~a)&0x01)
You should use ternary operator in this case.
#define makro(a) ((a) % 2 == 0) ? 1 : 0;
Answer is already there so better see that there are 2 points to note here :
A macro in the code is actually an inline expansion of its definition, as it is. Also, dont put semicolons after macro definition for that very reason.Also, enclose the entire macro definition within parantheses for correctness.
e.g. #define add(a) a+a
when used like add(2)*add(3) will be 2 + 2 * 3 + 3 =11
and not the expected 4*6=24.
2.If and else do not form a single statement , they are 2 statements connected together.
ie. if(2) --something--; else --something---; is correct.
Its not like the do while loop where do and while are a single statement.
#include
int main()
{ if(0) ; //---------> If and else are separate staements
else printf("Hello\n");
return 0;
} is a correct program.
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.)