Article directory
-
- Function Description
- example
- analyze
-
- MACRO_CHOOSE_HELPER
- MACRO_GLUE(x, y) x y
- MV(m, v)
- MASK_VALx
Function description
It is used to generate an integer according to the incoming mask and the corresponding value, and the unspecified mask bit is cleared.
MASK_VAL(BIT(1), 1)
, set bit1 to 1, the result is 2.MASK_VAL(BIT(1), 1, BIT(2), 1)
, set bit1 to 1, bit2 to 1, the result is 4.MASK_VAL(BIT(3), 0, BIT(4), 1, BIT_RNG(5, 6), 2)
, bit3 is cleared to 0, bit4 is set to 1, and the value of bit[5:6] is 2, the result is01010000
which is80
.
Example
#include <stdio.h> #define BIT(n) (1 << (n)) #define BIT_MASK_LEN(len) (BIT(len)-1) #define BIT_RNG(s, e) (BIT_MASK_LEN((e) - (s) + 1) << (s)) /* return the bit index of the lowest 1 in y. ex: 0b00110111000 --> 3 */ #define BIT_LOW_BIT(y) (((y) & amp;BIT(0)) ? 0 : (((y) & amp;BIT(1)) ? 1 : (((y) & amp;BIT(2) ) ? 2 : (((y) & amp;BIT(3)) ? 3 : \ (((y) & amp;BIT(4)) ? 4 : (((y) & amp;BIT(5)) ? 5 : (((y) & amp;BIT(6)) ? 6 : (( (y) & BIT(7)) ? 7 : \ (((y) & amp;BIT(8)) ? 8 : (((y) & amp;BIT(9)) ? 9 : (((y) & amp;BIT(10)) ? 10 : (( (y) & BIT(11)) ? 11 : \ (((y) & amp;BIT(12)) ? 12 : (((y) & amp;BIT(13)) ? 13 : (((y) & amp;BIT(14)) ? 14 : (( (y) & BIT(15)) ? 15 : \ (((y) & amp;BIT(16)) ? 16 : (((y) & amp;BIT(17)) ? 17 : (((y) & amp;BIT(18)) ? 18 : (( (y) & BIT(19)) ? 19 : \ (((y) & amp;BIT(20)) ? 20 : (((y) & amp;BIT(21)) ? 21 : (((y) & amp;BIT(22)) ? 22 : (( (y) & BIT(23)) ? 23 : \ (((y) & amp;BIT(24)) ? 24 : (((y) & amp;BIT(25)) ? 25 : (((y) & amp;BIT(26)) ? 26 : (( (y) & BIT(27)) ? 27 : \ (((y) & amp;BIT(28)) ? 28 : (((y) & amp;BIT(29)) ? 29 : (((y) & amp;BIT(30)) ? 30 : (( (y) & BIT(31)) ? 31 : 32 \ )))))))))))))))))))))))))))))))) /* get macro args numbers: COUNT_ARGS(1, 4, 6) -> 3 */ #define __COUNT_ARGS(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, .. .) N #define COUNT_ARGS(...) __COUNT_ARGS(, ##__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3 , 2, 1, 0) /* macro connect: MASK_VAL2, MASK_VAL2 */ #define __MACRO_CHOOSE_HELPER(base, count) base##count #define MACRO_CHOOSE_HELPER(base, count) __MACRO_CHOOSE_HELPER(base, count) /* macro expend: MACRO_GLUE(MASK_VAL2, (xxx)) -> MASK_VAL2(xxx)*/ #define MACRO_GLUE(x, y) x y /* get MASK_VALx data */ #define VARARG(base, ...) MACRO_GLUE(MACRO_CHOOSE_HELPER(base, COUNT_ARGS(__VA_ARGS__)), (__VA_ARGS__)) /** * @brief set mask value: MV(5, 0) -> (0 << 5) & amp; BIT(5) bit5 cleared \ * support BIT_RNG() */ #define MV(m, v) (((v) << BIT_LOW_BIT(m)) & (m)) #define MASK_VAL2(m, v) (MV(m, v)) #define MASK_VAL4(m1, v1, m2, v2) (MV(m1, v1) | MV(m2, v2)) #define MASK_VAL6(m1, v1, m2, v2, m3, v3) (MV(m1, v1) | MV(m2, v2) | MV(m3, v3)) #define MASK_VAL8(m1, v1, m2, v2, m3, v3, m4, v4) (MV(m1, v1) | MV(m2, v2) | MV(m3, v3) | MV(m4, v4)) #define MASK_VAL10(m1, v1, m2, v2, m3, v3, m4, v4, m5, v5) (MV(m1, v1) | MV(m2, v2) | MV(m3, v3) | MV(m4, v4) | MV(m5, v5)) #define MASK_VAL12(m1, v1, m2, v2, m3, v3, m4, v4, m5, v5, m6, v6) (MV(m1, v1) | MV(m2, v2) | MV(m3, v3) | MV(m4, v4) | MV(m5, v5) | MV(m6, v6)) #define MASK_VAL14(m1, v1, m2, v2, m3, v3, m4, v4, m5, v5, m6, v6, m7, v7) (MV(m1, v1) | MV(m2, v2) | MV(m3 , v3) | MV(m4, v4) | MV(m5, v5) | MV(m6, v6) | MV(m7, v7)) #define MASK_VAL16(m1, v1, m2, v2, m3, v3, m4, v4, m5, v5, m6, v6, m7, v7, m8, v8) (MV(m1, v1) | MV(m2, v2) | MV(m3, v3) | MV(m4, v4) | MV(m5, v5) | MV(m6, v6) | MV(m7, v7) | MV(m8, v8)) /** * @brief generate a mask value of up to 8 bits */ #define MASK_VAL(...) VARARG(MASK_VAL, __VA_ARGS__) int main(int argc, char *argv[]) {<!-- --> int count0 = MASK_VAL(BIT(1), 1); /* 0010 */ int count1 = MASK_VAL(BIT(1), 0, BIT(2), 1); /* 0100 */ int count2 = MASK_VAL(BIT(1), 1, BIT(2), 1); /* 0110 */ int count3 = MASK_VAL(BIT(1), 0, BIT(2), 0); /* 0000 */ int count4 = MASK_VAL(BIT(3), 0, BIT(4), 1); /* 10000 */ int count5 = MASK_VAL(BIT(3), 0, BIT(4), 1, BIT_RNG(5, 6), 2); /* 01010000 */ int count6 = MASK_VAL(BIT(3), 1, BIT(4), 0); /* 1000 */ printf("count0 = %d\ ", count0); printf("count1 = %d\ ", count1); printf("count2 = %d\ ", count2); printf("count3 = %d\ ", count3); printf("count4 = %d\ ", count4); printf("count5 = %d\ ", count5); printf("count6 = %d\ ", count6); return 0; }
result print
count0 = 2 count1 = 4 count2 = 6 count3 = 0 count4 = 16 count5 = 80 count6 = 8
Analysis
BIT
, BIT_MASK_LEN
, BIT_RNG
, BIT_LOW_BIT
, COUNT_ARGS
have been parsed separately ,refer to
- preprocessing
- bit manipulation
MACRO_CHOOSE_HELPER
MACRO_CHOOSE_HELPER
Why does the macro connection use two levels instead of directly
MACRO_CHOOSE_HELPER(base, cout) base##cout
When directly MACRO_CHOOSE_HELPER(base, cout) base##cout
, MASK_VAL, COUNT_ARGS(__VA_ARGS__))
passes in MASK_VAL
and COUNT_ARGS(__VA_ARGS__)
And ##
works on macro parameters, then the macro directly connects MASK_VAL
and COUT_ARGS
, and the result is MASK_VALCOUT_ARGS
So when the series of MACRO_CHOOSE_HELPER
is consistent with COUT_ARGS
, the effect of macro connection can be achieved
MACRO_GLUE(x, y) x y
Separate macro arguments x and y, where x is typically MASK_VALx
and y is (__VA_ARGS__)
So the final effect is MASK_VALx(__VA_ARGS__)
MV(m, v)
Set the corresponding mask value to v. If there are multiple mask bits, start with the first set mask
Mask bits that are not set have a value of 0
MASK_VALx
Separate the mask and value of MASK_VALx
, and call MV
to perform OR operation to get the final result.