Use of comma vs do-while in C macro - c

Is there a downside to doing this:
#define get_and_mark(name, b) get_val(name, &b), b = b | 0x80
rather than this:
#define get_and_mark(name, b) \
do { \
get_val(name, &b); \
b = b | 0x80; \
} while (0)
As far as I can see, the comma should also be safe for use in loops, branches etc.
But is it really?

If fixed up as Gerhardh says:
#define get_and_mark(name, b) (get_val(name, &(b)), (b) = (b) | 0x80)
then the first version can be used in an expression such as:
if (get_and_mark(name, b) != 0)
but the second cannot. Which semantic do you want? Do you want the invocation in an if condition to be a compile-time error?
Note that since b is mentioned multiple times in the expansion, you can't use get_and_mark(name, b[i++]). Also, note that you could use (b) |= 0x80 for the assignment in both variants:
#define get_and_mark(name, b) (get_val(name, &(b)), (b) |= 0x80)
#define get_and_mark(name, b) \
do { \
get_val(name, &(b)); \
(b) |= 0x80; \
} while (0)
You could use the comma operator in the second variant — though there's no need to do so.
Why not use an inline function?
static inline int get_and_mark(const char *name, int *b)
{
get_val(name, b);
return (*b |= 0x80);
}
You'd invoke it with get_and_mark(name, &b)? (Obviously, I'm guessing at the type of name, but fixing that if I'm wrong is easy.)

Related

Assigning value in C macro

Is it ok to assign a value in a C macro (i.e. have an lvalue in a macro)? For example, I would like to set a bit of a number to 1 based on the specified bit position. Is it ok to do this:
#define SET_BIT(data, pos) ((data) |= (1U << (pos)))
I've tested this and it works, but I feel like I'm walking on thin ice here and if I get used to macros like this, I would eventually run into problems.
Macros won't exist once the preprocessor has finished expanding them in the code. If you have a statement like
SET_BIT(some_data, some_pos);
then it will be replaced by
((some_data) |= (1U << (some_pos)));
in the code that is parsed and compiled.
In short, doing assignments in macros is perfectly fine.
The problem with the first SET_BIT_TO_VAL macro:
#define SET_BIT_TO_VAL(data, pos, val) (CLEAR_BIT(data, pos); (data) |= (1U << (pos)))
is that you put statements inside parentheses, like they were expressions. So that will not build.
The common way to group statements in a macro is to wrap them in a do { ... } while(0) loop:
#define SET_BIT_TO_VAL(data, pos, val) \
do { \
CLEAR_BIT(data, pos); \
SET_BIT(data, pos); \
} while (0)

define a macro that converts values between byte order

I want to create a macro that converts unsigned value conv to the opposite byte order of the current CPU. When not in a macro, it works well but let's say I want to do that as a macro. The compiler throws me an implict decleration when I try to use the macro. Take in mind that cpu_to_be32 and friends is a kernel-space functions, afaik at least.
#define be32_or_le32(conv) do { #ifdef __LITTLE_ENDIAN \
conv = cpu_to_be32(conv); \
#elif __BIG_ENDIAN \
conv = cpu_to_le32(conv); \
#endif } while (0)
u32 x = 0x12345678;
/* Convert the CPU's default byteorder to the opposite one */
be32_or_le32(x); /* Implict decleration */
Update: The answer below works really well but only without the do {} while (0), why when do.. added an error is thrown?
#ifdef __LITTLE_ENDIAN
#define be32_or_le32(conv) do { conv = cpu_to_be32(conv); } while (0)
#elif __BIG_ENDIAN
#define be32_or_le32(conv) do { conv = cpu_to_le32(conv); } while (0)
#endif
int __init sys_kernelmod_init(void)
{
u32 conv;
u32 x = 0x12345678;
/* Convert the CPU's default byteorder to the opposite one */
conv = be32_or_le32(x);
...
}
Don't use macros for things like this - use "static inline" functions. And try to give more sensible names - you are swapping the bytes in the 32-bit value, so it is a "byte swap" function. It is completely independent of the endianness of the system as you are always reversing the endianness, so there is no need to do any kind of conditional compilation. And stick to the standard type names (such as "uint32_t"), not home-made names (like "u32"), unless you have very good reason.
uint32_t bswap32(uint32_t x) {
return ((x >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | (x << 24));
}
Any decent compiler will optimise this to a single instruction if the target processor has a byte-swap instruction.
You cannot have preprocessor conditionals inside the macro expansion text.
Switch the structure to:
#ifdef __LITTLE_ENDIAN
#define be32_or_le32(conv) do { conv = cpu_to_be32(conv); } while (0)
#elif __BIG_ENDIAN
#define be32_or_le32(conv) do { conv = cpu_to_le32(conv); } while (0)
#endif

Comparator as function parameter

Is there any possibility in C89 to pass an operator as function parameter? I mean pass for expample <, ==, >= etc. Something like custom comparator in Java, but passed only with particular symbol. Maybe there is solution with special kind of preprocessor macro (I try to use '#' taken from processor macros)?
I know about pointers to functions, but I want something a little bit different.
Example:
void fun(int a, int b, comperator)
{
if(a comperator b)
........
}
You can use a macro. But remember - a macro is not a function; it has different (ugly) syntax, some specific problems, some advantages, etc.
Suppose you have a function:
int fun(int x, int y)
{
if (x < y)
return 1;
else if (x < 2 * y)
return 2;
else if (x < 2 * y)
return 3;
else
return 4;
}
To use a different comparator, first convert it to a macro:
#define FUN(x, y) \
x < y ? 1 : \
x < 2 * y ? 2 : \
x < 3 * y ? 3 : \
4
This conversion is very ugly (it will usually by more ugly than in my example), and not always possible, but now you can add a comparator:
#define FUN(x, y, c) \
x c y ? 1 : \
x c 2 * y ? 2 : \
x c 3 * y ? 3 : \
4
Usage:
printf("%d\n", FUN(3, 5, <));
(Note: in macros, you should add parentheses around variables, explained e.g. here; I omitted them for clarity).
No You cant , just pass it like a string and make a test in the function
The easiest way would be to use enums that represent the comparators but with some manipulation you could write a macro wrapper to fun() that calls funLT(), funGT... or enumerates the comparators to LT,GT,.. for use in a switch case.
If fun(...) is rather large you probably want to use enums and a switch case inside the function at the appropriate location.
enum{LT,GT,EQ,NE,LE,GE};
#define fun(a,b,OP) fun_(a,b,
(0 OP 1) \
? (1 OP 0) \
? NE \
: (0 OP 0) \
? LE \
: LT \
: (0 OP 0) \
? (1 OP 0) \
? GE \
: EQ \
: GT \
)
fun(int a, int b, int op){
//code
switch(op){
case GE: //etc...
}
//more code
}
If the function is small you may instead prefer to have separate functions for each operator
#define fun(a,b,OP) \
(0 OP 1) \
? (1 OP 0) \
? funNE((a),(b)) \
: (0 OP 0) \
? funLE((a),(b)) \
: funLT((a),(b)) \
: (0 OP 0) \
? (1 OP 0) \
? funGE((a),(b)) \
: funEQ((a),(b)) \
: funGT((a),(b))

Compare preprocessor macros for equality

I have some crude generated header from some .dbc files.
Since a few of the messages represent elements from an array the structure is equal and so the generated Macros are equal. Since I fill some array of struct in the code I would like to save effort and use the same macro for all objects, but to ensure the definitions have not changed I would like to test at compile time if the macros are equal.
Example:
#define GET_PATTERN_01_PATTERNPOINT02Y(buf) (0 \
| (uint16)(-(uint16)((buf[7] >> 6) & 0x01) << 15) \
| (uint8)(+(uint8)((buf[6] >> 0) & 0xff) << 0) \
| (uint16)(+(uint16)((buf[7] >> 0) & 0x7f) << 8) \
)
#define GET_PATTERN_02_PATTERNPOINT04Y(buf) (0 \
| (uint16)(-(uint16)((buf[7] >> 6) & 0x01) << 15) \
| (uint8)(+(uint8)((buf[6] >> 0) & 0xff) << 0) \
| (uint16)(+(uint16)((buf[7] >> 0) & 0x7f) << 8) \
)
#if GET_PATTERN_01_PATTERNPOINT02Y != GET_PATTERN_02_PATTERNPOINT04Y
# error blah
#endif
Is this Possible?
If there is some solution in C++ that may also help. But the macros are fixed.
This is a horrible hack, but seems to work for your example for GCC and C11 at least:
#include <assert.h>
#include <string.h>
...
#define STRINGIFY(x) STRINGIFY_(x)
#define STRINGIFY_(x) #x
#define ASSERT_SAME(m1, m2) \
static_assert(strcmp(STRINGIFY(m1(xxx)), STRINGIFY(m2(xxx))) == 0, \
#m1"() and "#m2"() differ!")
ASSERT_SAME(GET_PATTERN_01_PATTERNPOINT02Y, GET_PATTERN_02_PATTERNPOINT04Y);
You might need to pass -std=c11 or -std=gnu11, though the latter shouldn't be needed here.
Explanation:
STRINGIFY(x) returns the expansion of x as a string literal. We need to do the stringification in two steps using STRINGIFY_() because # suppresses macro expansion. (With one step we'd get "<x>" instead of "expanded version of <x>".)
GCC has a built-in version of strcmp() (__builtin_strcmp()) which is used here. It just happens to be able to compare constant strings at compile-time. The code breaks if you pass -fno-builtin (unless you explicitly use __builtin_strcmp()).
static_assert is a C11 compile-time assertion.
With the three ingredients above we can stringify the expanded macros (passing some dummy token that's likely to be unique for the argument) and compare the strings at compile-time.
Yes, this is a hack...
In C++11 there are safer ways to compare strings at compile time -- see e.g. this answer.
As a side note, you could do this at run-time too with zero overhead for GCC and Clang. (The version above won't work for Clang as it's pickier about strcmp(...) == 0 not being an integer constant expression as required by static_assert.) A run-time check like
if (strcmp(STRINGIFY(m1(xxx)), STRINGIFY(m2(xxx))) != 0) {
*report error and exit*
}
gets completely optimized out when the macros are equal. Not even the strings are kept in the read-only data segment (just checked). It's a more robust approach if you can live with having to run the program to discover the problem.
It possible to do this a bit better by using variadic macros to do the stringification:
#define STRINGIFY_VARIADIC(...) #__VA_ARGS__
#define EXPAND_AND_STRINGIFY_VARIADIC(...) STRINGIFY_VARIADIC (__VA_ARGS__)
#define STATIC_ASSERT_IDENTICAL_EXPANSIONS(macro_a, macro_b) \
_Static_assert ( \
( \
__builtin_strcmp ( \
EXPAND_AND_STRINGIFY_VARIADIC (macro_a), \
EXPAND_AND_STRINGIFY_VARIADIC (macro_b) ) \
== 0 \
), \
"expansions of " #macro_a " and " #macro_b " differ" )
This has two advantages: it works with macros which expand to tuples
(e.g. #define FOO thing1, thing2), and it works with macros which take
arguments (without a dummy token like xxx in the other solution). Note that
the final expansions are compared, not the full expansion histories.
So given these #defines:
#define FOO foo
#define BAR bar
#define ARG_DOUBLER(arg) arg, arg
#define ARG_ITSELF(arg) arg
#define OTHER_ARG_DOUBLER(arg) ARG_ITSELF (arg), ARG_ITSELF (arg)
#define SECOND_ARG_NUKER(arg1, arg2) arg1
All of these will trigger a compile-time error:
STATIC_ASSERT_IDENTICAL_EXPANSIONS (FOO, BAR);
STATIC_ASSERT_IDENTICAL_EXPANSIONS (ARG_DOUBLER (x), ARG_DOUBLER (y));
STATIC_ASSERT_IDENTICAL_EXPANSIONS (x, ARG_ITSELF (y));
STATIC_ASSERT_IDENTICAL_EXPANSIONS (SECOND_ARG_NUKER (x, y), y);
While of these will compile ok:
STATIC_ASSERT_IDENTICAL_EXPANSIONS (FOO, foo);
STATIC_ASSERT_IDENTICAL_EXPANSIONS (ARG_DOUBLER (x), ARG_DOUBLER (x));
STATIC_ASSERT_IDENTICAL_EXPANSIONS (x, ARG_ITSELF (x));
STATIC_ASSERT_IDENTICAL_EXPANSIONS (SECOND_ARG_NUKER (x, y), x);

Can macro perform compound assignments

I read little gnu online docs about macro and little confused about this sentence:
Also multi-character operators such as += can be formed by token pasting
So I wander if macro can perform compound assignments,How?
#define PASTE(a,b) a##b
int foo;
foo PASTE(+,=) 2;
The only time I've ever seen this be useful was in the inner loop of a bytecode interpreter, which tends to look like a gigantic case statement with very repetitive code in each arm:
case OP_add: {
if (sp < 2) goto underflow;
double x = stack[--sp];
stack[sp-1] += x;
} break;
Repeat for each supported binary arithmetic operator. With the ability to token-paste, you can generate them all from a macro:
#define ARITH_BINOP(name, oper) case OP_##name: { \
if (sp < 2) goto underflow; \
double x = stack[--sp]; \
stack[sp-1] oper##= x; \
} break /* deliberate absence of semicolon */
and then, in the switch, you can just write
ARITH_BINOP(add, +);
ARITH_BINOP(sub, -);
ARITH_BINOP(mul, *);
/* etc */
I think, documentation says about cases like:
#define COMPST(x, y) x ## y
int
foo(int x)
{
return x COMPST(+, =) 2;
}
Of course macros can perform anything you can achieve in C code:
#define INCREMENT(x) ((x) += 1)
main() {
int n=42;
INCREMENT(n);
}
the line you read means another thing which I suspect you are not interested in...

Resources