I have an embedded C source code. In it's definitions, it has a lot of #define lines like following:
#define XNV_SPI_TX(x) st(U1CSR &= 0xFD; U1DBUF = (x);)
any idea what does
st( )
means and does?
I am using IAR as compiler and toolchain.
Thanks to comments, here is what I found:
/* (The while condition below evaluates false without generating a
* constant-controlling-loop type of warning on most compilers.)
*/
#define st(x) do { x } while (__LINE__ == -1)
This construct is used to prevent if/else conditionals show unexpected behavior.
For example if you have something like
#define assign() a=1;b=0;
it would not behave as expected in if/else statement.
Related
I want to deprecate a macro in such a way that it will print a nice warning even if used inside of a #if statement.
This answer is very nearly what I want, but it throws an error when the macro is accessed from within a #if statement.
#include <stdio.h>
#define DEPRECATED_CONSTANT _Pragma ("GCC warning \"Deprecated constant!\"") 0
#define DEPRECATED_FUNCTION(...) _Pragma ("GCC warning \"Deprecated function!\"") printf(__VA_ARGS__)
int main() {
// Prints a warning (good)
int n = DEPRECATED_CONSTANT;
// Prints a warning (good)
DEPRECATED_FUNCTION("%d\n", n);
// Throws an error (bad)
#if DEPRECATED_CONSTANT
return 1;
#else
return 2;
#endif
}
The error is:
error: missing binary operator before token "("
Bonus points if you can find me a cross-platform compatible solution!
EDIT
I'm trying to handle a breaking change in a library gracefully - I want users to have a nice, clear warning (or error) whenever they use an old macro, so it will be clear that they need to migrate their code to using the new macro. These pragma solutions only work if the value of that constant is used in code, not if the value is accessed in a preprocessor directive.
According to the answers provided below, it seems like there's not a solution to this problem (except possibly when using clang?). Thanks, everyone.
I want to deprecate a macro in such a way that it will print a nice
warning even if used inside of a #if statement.
I was going to suggest the comma operator, but that doesn't seem to work because the _Pragma macro probably yields no real code. Also, gcc, at least, explicitly says you can't do what you suggested with _Pragma():
https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html
The standard is unclear on where a _Pragma operator can appear. The
preprocessor does not accept it within a preprocessing conditional
directive like ‘#if’. To be safe, you are probably best keeping it out
of directives other than ‘#define’, and putting it on a line of its
own.
PS - clang 8.1.0 didn't error on your program and gave the warnings you want ...
As #jschultz410 mentions, what you are trying to do is explicitly forbidden in gcc (see https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html).
Nested macros seem appropriate for such a use case:
#include <stdio.h>
#define DEPRECATED_CONSTANT_VALUE 0
#define DEPRECATED_CONSTANT _Pragma ("GCC warning \"Deprecated constant!\"") DEPRECATED_CONSTANT_VALUE
#define DEPRECATED_FUNCTION(...) _Pragma ("GCC warning \"Deprecated function!\"") printf(__VA_ARGS__)
int main() {
// Prints a warning (good)
int n = DEPRECATED_CONSTANT;
// Prints a warning (good)
DEPRECATED_FUNCTION("%d\n", n);
// Throws an error (bad)
#if DEPRECATED_CONSTANT_VALUE
return 1;
#else
return 2;
#endif
}
Yes, this is kind of gross, but in the land of preprocessor logic we're already giving up on any kind of design elegance in the first place. At least this way the macro interface is maintained in non-preprocessor code. (Yes, this would not print the preprocessor warning in the #if statement, but unfortunately that's not possible with gcc).
I find it difficult to understand the working of a macro defined with the help of preprocessor directives.
The macro,
TRXEM_SPI_BEGIN()
is defined with the help of two preprocessor directives refereed from two header files. Firstly, I wish to state the declaration of the said macro.
#define TRXEM_SPI_BEGIN() st( TRXEM_PORT_OUT &= ~TRXEM_SPI_SC_N_PIN; NOP();)
As the declaration of macro st () is missing here, I found it defined in a different header file and ti is shown below.
#define st(x) do { x } while (__LINE__ == -1)
Now after combining two macros, the true definition of macro TRXEM_SPI_BEGIN() must be,
#define TRXEM_SPI_BEGIN() do {
( TRXEM_PORT_OUT &= ~TRXEM_SPI_SC_N_PIN; NOP(); )
} while (__LINE__ == -1)
This code is written to work inside a microcontroler where TRXEM_PORT_OUT, RXEM_SPI_SC_N_PIN are memory mapped registers and NOP initiates an instruction cycle that does nothing.
As per my understanding, __LINE__ means the line of code in the c file where __LINE__ lies. That line can never be equal to -1. i.e. this loopmust always be running only once provided the __LINE__ can never be placed in -1 place in a .c file. Simply put, -1 can never be the value of __LINE__.
Therefore, I believe a do while() loop here is unnecessary and the same output could have been achieved by simply without using any looping.
I do not understand the functioning of this macro. I would so much appreciate if someone could elaborate on it.
As per my understanding, means the line of code in the c file
where __LINE__ lies. That line can never be equal to -1. i.e. this
loopmust always be running only once provided the __LINE__ can never
be placed in -1 place in a .c file. Simply put, -1 can never be the
return value to a __LINE__.
Your understanding is exactly correct here. It is there to make sure the code runs exactly once.
Think of following scenario:
#define BAZ foo();bar();
Now if you do
if(some_cond) BAZ;
This is equivalent to:
if(some_cond) foo();
bar();
Which is most possibly not something you want. So you change it to:
#define BAZ {foo();bar();}
This works fine if written as if(some_cond) foo() else wow(); but would fail compilation if written as if(some_cond) foo(); else wow();
So you define BAZ as
/* No semicolon at end */
#define BAZ do {foo();bar();} while(condition_which_is_always_false)
And you can now write the natural code with intuitive semicolon at end.
In your case, condition_which_is_always_false is __LINE__ == -1
I'm trying to pass the parameters to macro SETBIT with another predefined macro like this:
#define SETBIT(ADDRESS,BIT,N) {(N) ? (ADDRESS &= ~(1<<BIT)) : (ADDRESS |= (1<<BIT))}
#define DAC_SYNC PORTB,3,POS
SETBIT(DAC_SYNC);
However I receiver error:
macro SETBIT requires 3 parameters only 1 given
There is an article with the following recommendations:
to prevent misnesting of arithmetic operations: #define foo (a,b) or #define bar(x) lose((x))
But even though I still have an error. BTW, reading the article I've indicated I can make the following conclusion: preprocessor expands ALL macroses appearing. But actually it looks like macro #define DAC_SYNC PORTB,3,POS is not expanding by preprocessor.
Could anyone make more clear how the GCC's preprocessor works?
This works:
#define SETBIT2(ADDRESS,BIT,N) ((N) ? (ADDRESS &= ~(1<<BIT)) : (ADDRESS |= (1<<BIT)))
#define SETBIT(PARAMS) SETBIT2(PARAMS)
#define PORTB 5
#define POS 7
#define DAC_SYNC PORTB,3,POS
int main() {
int a = SETBIT(DAC_SYNC);
return 0;
}
Just for the sake of completeness, that same manual you are linking to also states:
The number of arguments you give must match the number of
parameters in the macro definition. When the macro is expanded, each
use of a parameter in its body is replaced by the tokens of the
corresponding argument.
So ooga's example is a nice demonstration of how macro expansion works recursively, first the outer macro gets expanded, then the argument.
I'm trying to make my header file easily changeable with macros. I'm debugging my code and it seems these MACROS are not doing what they are supposed to. Can someone tell me how I achieve the following effect? LED_ID_AMS etc.
#define LED_NUMBER (2)
#define LED_ID_X (0)
#define LED_ID_Y (1)
#define LED_PIN_X (0)
#define LED_PIN_Y (3)
#define LED_PORT_X (PORTE)
#define LED_PORT_Y (PORTG)
#define LED_DD_X (DDRE)
#define LED_DD_Y (DDRG)
#define LED_PORT(LED_ID_X) (LED_PORT_X)
#define LED_PORT(LED_ID_Y) (LED_PORT_Y)
#define LED_PIN(LED_ID_X) (LED_PIN_X)
#define LED_PIN(LED_ID_Y) (LED_PIN_Y)
#define LED_DD(LED_ID_X) (LED_DD_X)
#define LED_DD(LED_ID_Y) (LED_DD_Y)
What am I trying to achieve?
I'm trying to make it so I can loop through the port init like so:
for(i=0;i<LED_NUMBER;i++){
/* set data direction to output*/
LED_DD(i)|=((0x01)<<LED_PIN(i));
/* turn on led */
LED_PORT(i)|=((0x01)<<LED_PIN(i));
}
You will regret using too many macros later. Actually, you're regretting it already, as they don't work and, being macros, they are very difficult to debug.
Just a few points:
your LED_PIN(i) expressions are always expanding to 0
your LED_PORT(i) expressions are always expanding to PORTE whatever that may be
For instance LED_PIN(LED_ID_X) expands to LED_PIN_X. Note, macro parameter LED_ID_X is not used at all. Instead, LED_PIN_X simply expands to 0.
This should scream warnings at you, as e.g. LED_PORT(SOME_ARG) has several definitions. And in LED_PORT(LED_ID_X) the LED_ID_X is just a dummy argument, with absolutely no relation to your constant LED_ID_X.
You can make your code equally readable by using a constant array, perhaps used from macros like you try to do here.
Unless there are a massive number of LED_ID_<foo>, this is at best a minor simplification. Don't do that. If there is a lot of code futzing around with those is mostly the same way, it might make sense to define a macro that iterates some action over each of them, i.e.:
#define FROB_LEDS \\
action(LED_ID_X); \\
action(LED_ID_Y); \\
action(LED_ID_Z);
and define action(X) locally as a macro to do the action on LED X, FROB them, and undefine action again. Quite ugly, true.
You'll have to add at least one of:
arrays
inline functions
more complicated macros
And it also seems to me that dereferencing of hardware addresses will be required.
For example, using macros, you can define:
#define LED_PORT(i) *(uint16_t *)( \
(i) == LED_ID_X ? LED_PORT_X : \
(i) == LED_ID_Y ? LED_PORT_Y : \
etc)
where:
#define LED_ID_X (0)
#define LED_ID_Y (1)
#define LED_PORT_X (PORTE)
#define LED_PORT_Y (PORTG)
#define PORTE (0x11112222U) // example only
#define PORTG (0x33334444U) // example only
Here uint16_t is only a guess: I'm assuming 16-bit ports in a 32-bit address space.
Or, using arrays and C99's designated initializers:
const uint32_t LED_PORT[] = {
[LED_ID_X] = LED_PORT_X,
[LED_ID_Y] = LED_PORT_Y
};
#define LED_PORT(i) (*(uint16_t *)LED_PORT[i])
And of course, without C99 you can use just:
const uint32_t LED_PORT[] = {LED_PORT_X, LED_PORT_Y};
which assumes that LED_ID_X is 0, etc.
I am using a #ifdef block to conditionally include a block of code based on -Dflag passed to the compiler.
Is there a way to implement this with an if?
Something along the lines of:
if (defined(flag)) {
}
You use preprocessor to produce a different flag, which could be tested with a run-time if statement, like this:
#ifdef flag
#define flag_defined 1
#else
#define flag_defined 0
#endif
Now you can do this:
if (flag_defined) ...
If you define a macro so that it evaluates to either zero or nonzero, then you can use it in the condition of the if statement. Since it's a compile-time constant, in case it's zero, the dead code eliminator pass in the compiler will remove the unreachable code anyway.
If you are willing to give flag a value (0 or 1) instead of defining it or not, you can do
cc -Dflag=1 file.c
with
if (flag) { ... }
without messing up your code with ugly #ifdefs. You are also protected against forgetting to define flag at all: in this case your compiler treats flag as an identifier. Since you never declared it, you'll get a compile time error about an undeclared or undefined symbol flag.
No, you can't use a C if statement to check if a preprocessor token is defined.
You can use one of these forms though
#ifdef flag
...
#endif
#if defined(flag)
...
#endif
You can however check if the token evaluates to a true/false C expression,
if you use -Dflag=1 you can do
if (flag) {
...
}
And if you want to turn it off, you can define the macro as -Dflag=0
Following this you can define a new preprocessor token that you can check with a C if statement. e.g.
#ifdef flag
#define FLAG_SET 1
#else
#define FLAG_SET 0
#endif
if(FLAG_SET) { //the flag macro was defined
...
}
If all you want to do is is check whether the flag is defined, there's no point to all of this, just use #ifdef. With a C if statement, the most C compilers will optimize away the code, there's nothing you could change at runtime to get any benefit of not using the preprocessor.
#ifdef FLAG
#define FLAG_VALUE 1
#else
#define FLAG_VALUE 0
#endif
int flag = FLAG_VALUE;
...
if(flag)
{
....
}
Alternatively just use -DFLAG_VALUE=1 or -DFLAG_VALUE=0 as appropriate and use FLAG_VALUE directly.
If you plan on being able to change the FLAG_VALUE at runtime you will need a variable. If you change in non-obvious ways (e.g. via a debugger or through other loader trickery) make sure to declare it volatile, otherwise the compiler might be able to do dead-code elimination and remove huge chunks of code.
Also, if you don't plan on changing the value of flag after initializing, then you should probably make it const.