What does ## do in C?
Example:
typedef struct
{
unsigned int bit0:1;
unsigned int bit1:1;
unsigned int bit2:1;
unsigned int bit3:1;
unsigned int bit4:1;
unsigned int bit5:1;
unsigned int bit6:1;
unsigned int bit7:1;
} _io_reg;
#define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bit##bt
(I know what it all does besides the ## part.)
It is string concatenation, as part of the preprocessor macro.
(In this context, "string" refers to a preprocessor token of course, or a "string of source code", and not a C-string.)
It's called the pasting operator; it concatenates the text in bt with the text bit. So for example, if your macro invocation was
REGISTER_BIT(x, 4)
It would expand to
((volatile _io_reg*)&x)->bit4
Without it, you couldn't put a macro argument directly beside text in the macro body, because then the text would touch the argument name and become part of the same token, and it'd become a different name.
The operator ## concatenates two arguments leaving no blank spaces between them:
#define glue(a,b) a ## b
glue(c,out) << "test";
That is the token pasting operator.
That's part of the macro definition.
It allows you to concatenate strings inside the macro.
In your case, you can use bt from 7 to 0 like this:
REGISTER_BIT(myreg, 0)
and it will be expanded as:
((volatile _io_reg*)&myreg)->bit0
Without this, you'd have to define the bit part of the macro as one of the macro's arguments:
#define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bt
where the usage would be:
REGISTER_BIT(myreg, bit0)
which is more cumbersome.
This also allows you to build new names.
Assume you have these macros:
#define AAA_POS 1
#define AAA_MASK (1 << AAA_POS)
#define BBB_POS 2
#define BBB_MASK (1 << BBB_POS)
and you want a macro that extracts AAA from a bit vector. You can write it like this:
#define EXTRACT(bv, field) ((bv & field##_MASK) >> field##_POS)
and then you use it like this:
EXTRACT(my_bitvector, AAA)
It's not a C construct, it's a preprocessor feature. In this case it's meant to evaluate the bt variable and concatenate it with the bit prefix. Without the hashes you would have bitbt there, which obviously would not work.
Here's an example from ffmpeg, a macro that registers both audio and video filters:
#define REGISTER_FILTER(X, x, y) \
{ \
extern AVFilter ff_##y##_##x; \
if (CONFIG_##X##_FILTER) \
avfilter_register(&ff_##y##_##x); \
}
and usage can be:
REGISTER_FILTER(AECHO,aecho,af);
REGISTER_FILTER(VFLIP,vflip,vf);
Related
I found the code below in a project and I'm having problems understanding why GCC doesn't complaint since dlc is called before it has been defined.
#define CAN_SET_DLC(dlc) (CANCDMOB |= (dlc))
typedef struct
{
uint8_t mob_n;
uint8_t handle;
long id;
long id_msk;
uint8_t dlc;
uint8_t data_pt[8];
uint8_t status;
} can_msg;
¿The variable type of dlc should also be defined?:
define CAN_SET_DLC(uint8_t dlc) (CANCDMOB |= (dlc))
The preprocessor has no knowledge of variables or any language construct. It is just a token processor.
In #define a(b) ( b + 1 ) this means that anytime the preprocessor encounters a(foo) in the source text, it will replace it with ( foo + 1 ). Then the compiler will check whether it is correct C.
This is the normal way to define macro with arguments: https://gcc.gnu.org/onlinedocs/cpp/Macro-Arguments.html#Macro-Arguments
Macros just replace text basically so you have to take care about variable type.
No, macros only substitute text (more precisely tokens) and it is done before actual C code compilation. The preprocessor does not know anything about C language.
The preprocessed source code then is compiled by the C compiler.
#define CAN_SET_DLC(dlc) ((DLC) |= CANCDMOB)
#define CANCMOB 0x34
int foo(uint8_t z)
{
CAN_SET_DLC(z);
return z;
}
will result in
int foo(uint8_t z)
{
((z) |= 0x34);
return z;
}
I'm trying to create a macro in C in order to create the correct pragma declaration.
_pragma(section .BLOCK1) //Correct but deprecated
_pragma(section ".BLOCK1") //Correct without warning
Following code is working, but the compiler gives me a warning (deprecated declaration):
#define DO_PRAGMA(x) _Pragma(#x)
#define PRAGMA(number) \
DO_PRAGMA(section .BLOCK##number)
PRAGMA(1)
How I can include the double quotes in the macro?
I have already tried inserting "\"", but it is not working because the string is interpreted directly.
You can pass this to a helper macro which expands and stringifies the arguments.
#define _stringify(_x) #_x
#define DO_PRAGMA(a) _Pragma(_stringify(a))
#define PRAGMA(number) \
DO_PRAGMA(section _stringify(.BLOCK##number))
The correct way to add double quotes to a macro is indeed to use backslash i.e.:
#define STRING "\"string\""
"string" is now stored in STRING.
To concatenate a number into your macro string you can do something like, but it needs to be stored in non const char array:
#define STRING "section \".BLOCK%d\""
#define CONV(str, n) sprintf(str, STRING, n)
//...
char str [50];
CONV(str, 1);
DO_PRAGMA(str);
//...
If you haven't already, check pragma documentation and this usage example.
uint32_t fail_count = 0;
...
if(is_failed)
if(fail_count < UINT32_MAX - 1 )
++fail_count;
It works fine, but this code is fragile. Tomorrow, I may change the type of fail_count from uint32_t to int32_t and I forget to update UINT32_MAX.
Is there any way to assert fail_count is a uint32_t at the function where I have written my ifs?
P.S. 1- I know it is easy in C++ but I'm looking for a C way.
P.S. 2- I prefer to use two asserts than relying on the compiler warnings. Checking the number size via sizeof should work but is there any way to distinguish if type is unsigned?
As of C11, you can use a generic selection macro to produce a result based on the type of an expression. You can use the result in a static assertion:
#define IS_UINT32(N) _Generic((N), \
uint32_t: 1, \
default: 0 \
)
int main(void) {
uint32_t fail_count = 0;
_Static_assert(IS_UINT32(fail_count), "wrong type for fail_count");
}
You could of course use the result in a regular assert(), but _Static_assert will fail at compile time.
A better approach could be dispatching the comparison based on type, again using generic selection:
#include <limits.h>
#include <stdint.h>
#define UNDER_LIMIT(N) ((N) < _Generic((N), \
int32_t: INT32_MAX, \
uint32_t: UINT32_MAX \
) -1)
int main(void) {
int32_t fail_count = 0;
if (UNDER_LIMIT(fail_count)) {
++fail_count;
}
}
As you mentioned GCC, you can use a compiler extension to accomplish this in case you are not using C11:
First write a macro that emulates the C++ is_same. And then call it with the types you want to compare.
A minimal example for your particular case:
#include<assert.h>
#define is_same(a, b) \
static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), #a " is not unsigned int")
int main()
{
int fail_count = 0;
is_same(fail_count, unsigned int);
}
The compiler asserts:
<source>: In function 'main':
<source>:4:3: error: static assertion failed: "fail_count is not unsigned int"
static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), #a " is not unsigned int")
^~~~~~~~~~~~~
<source>:9:5: note: in expansion of macro 'is_same'
is_same(fail_count, unsigned int);
^~~~~~~
See Demo
What about a low-tech solution that works even with K&R C and any compiler past and present?
Place the right comment in the right place:
/*
* If this type is changed, don't forget to change the macro in
* if (fail_count < UINT32_MAX - 1) below (or file foobar.c)
*/
uint32_t fail_count = 0;
With a proper encapsulation this should refer to exactly one place in the code.
Don't tell me you increment the fail count in many places. And if you do, what
about a
#define FAIL_COUNT_MAX UINT32_MAX
right next to the declaration? That's more proper and clean code anyway.
No need for all the assertion magic and rocket sciencery :-)
Let's start with the code and the error.
#define BitMap_getMask(range) (((~(unsigned int)0>>(31-range.b+range.a))<<range.a))
#define BitMap_get(x, range) (x & BitMap_getMask(range))
#define awesome (range){4,6}
...................
printf("%08x\n", BitMap_get(0xEEEEEEEE, awesome));
Now the error from the compiler. Line 29, the line with the printf.
error: macro "BitMap_getMask" passed 2 arguments, but takes just 1
error: 'BitMap_getMask' undeclared (first use in this function)
I'm working on a small library which will help me with bitwise operations. When trying to use a macro within another macro I am getting this error.
When range is expanded to {4,6} and passed to BitMap_getMask, what you're getting is BitMap_getMask({4,6}) which is 2 arguments, whereas BitMap_getMask expects 1 argument.
Furthermore, the pre-processor only does text replacement for these macros. It is unaware of type. It will replace every instance of text "range" with text "{4,6}" so you don't have a type (struct range) or instance of a type, that you can use, just some text, so "range.a" and "range.b" are also not going work; they would result something like "{4,6}.a" and "{4,6}.b"
Not valid C.
C99 supports inline functions, and there is almost no excuse for using pre-processor macros in C these days. They are trouble (one good use of course is include guards). Inline functions are in the domain of the compiler and properly type-checked.
struct awesome
{
unsigned int a;
unsigned int b;
};
...
static inline unsigned int BitMap_get(unsigned int x, awesome range)
{
return (x & BitMap_getMask(range));
}
static inline unsigned int BitMap_getMask(awesome range)
{
return (((~(unsigned int)0>>(31-range.b+range.a))<<range.a));
}
...
awesome range =
{
.a = 4,
.b = 6,
};
unsigned int x = 0xEEEEEEEE;
unsigned int bm = BitMap_get(x, awesome);
...
This might be what you need
#define BitMap_getMask(range) \
(((~(unsigned int) 0 >> (31 - (range).max + (range).min)) << (range).min))
#define BitMap_get(x, range) \
((x) & BitMap_getMask(range))
#define awesome \
((struct {int min; int max;}){4, 6})
the error was due to the expansion of {4, 6}.
Is is possible to define a macro BREF(...):
struct bits
{
int b0:1;
int b1:1;
int b2:1;
int b3:1;
int b4:1;
int b5:1;
int b6:1;
int b7:1;
}
#define BREF(var,bit) ????
#define BAR 4
#define ALIAS BREF(foo,BAR)
unsigned char foo;
such that this statement:
ALIAS = 1;
expands to this:
((struct bits *)&foo)->b4 = 1;
and this:
int k = ALIAS;
to this:
int k = ((struct bits *)&foo)->b4;
So far, this is my implementation of BREF(...):
#define BREF(var,bit) (((struct bits *) &(var))->b##bit)
However, this only works if bit is a literal numeral. I want to be able to pass in a macro variable that expands into a number. How can I make the C preprocessor expand bit before concatenating it to b?
The trick is that the C preprocessor will expand macro arguments only if they are not being used with the stringizing (#) or token-pasting (##) operators. So, to make it work with a macro that expands to a numeric literal, add an extra layer of macros like so:
#define CONCAT(x, y) x ## y
#define BREF(var,bit) (((struct bits *) &(var))-> CONCAT(b, bit))
With this definition, bit is no longer a direct argument of the token-pasting operator, so if it's a macro, it gets expanded before the token-pasting.
You can use an extra step of expansion, like this:
#define BITATTR(num) b##num
#define BREF(var,bit) (((struct bits *) &(var))->BITATTR(bit))