Weird if condition in c: if( ((void)(d), 0) ) {...} - c

I read Xen source code and saw something like this:
#define is_domain_direct_mapped(d) ((void)(d), 0)
is_domain_direct_mapped is then used in a if statement as follows (d is a pointer to a struct variable):
if( is_domain_direct_mapped(d) ) {...}
So after compiler replaces is_domain_direct_mapped with its definition, we have something like:
if( ((void)(d), 0) ) {...}
The above if statement is very weird to me. This is the first time I see this kind of statement. How is it supposed to work?

It’s meant to always produce 0 but also evaluate d, in case it’s something with side-effects like p++.
As for why you would want to always produce 0: the implementation is different on ARM.
#define is_domain_direct_mapped(d) ((d) == hardware_domain && dom0_11_mapping)
Notice how d is evaluated exactly once here too.
Some discussion from when this was first introduced as confirmation – Re: [Xen-devel] [PATCH v3 1/3] xen/x86: introduce is_domain_direct_mapped(d) as (0) on x86:
When I've implemented this defined in common/memory.c, Jan told me to
use [1]:
#define is_domain_is_direct_mapped(d) ((void)(d), 0)
I suspect you want the same things here.
referencing Re: [v4] xen/arm: Allow balooning working with 1:1 memory mapping:
And you'll want to make sure (even if unlikely to be needed in
practice) that you evaluate the macro argument exactly once in both
flavors, i.e. in the case here
#define is_domain_direct_mapped(d) ((void)(d), 0)

This is the comma operator.
The left member (in your case d) is evaluated for its side effects and then discarded. The right member (0) gives the result.

Related

Defining a function as macro

I am trying to understand defining functions as macros and I have the following code, which I am not sure I understand:
#define MAX(i, limit) do \
{ \
if (i < limit) \
{ \
i++; \
} \
} while(1)
void main(void)
{
MAX(0, 3);
}
As I understand it tries to define MAX as an interval between 2 numbers? But what's the point of the infinite loop?
I have tried to store the value of MAX in a variable inside the main function, but it gives me an error saying expected an expression
I am currently in a software developing internship, and trying to learn embedded C since it's a new field for me. This was an exercise asking me what the following code will do. I was confused since I had never seen a function written like this
You are confused because this is a trick question. The posted code makes no sense whatsoever. The MAX macro expands indeed to an infinite loop and since its first argument is a literal value, i++ expands to 0++ which is a syntax error.
The lesson to be learned is: macros are confusing, error prone and should not be used to replace functions.
You have to understand that before your code gets to compiler, first it goes through a preprocessor. And it basically changes your text-written code. The way it changes the code is controlled with preprocessor directives (lines that begin with #, e.g. #include, #define, ...).
In your case, you use a #define directive, and everywhere a preprocessor finds a MAX(i, limit) will be replaced with its definition.
And the output of a preprocessor is also a textual file, but a bit modified. In your case, a preprocessor will replace MAX(0, 3) with
do
{
if (0 < 3)
{
0++;
}
} while(1)
And now the preprocessor output goes to a compiler like that.
So writing a function in a #define is not the same as writing a normal function void max(int i, int limit) { ... }.
Suppose you had a large number of statements of the form
if(a < 10) a++;
if(b < 100) b++;
if(c < 1000) c++;
In a comment, #the busybee refers to this pattern as a "saturating incrementer".
When you see a repeated pattern in code, there's a natural inclination to want to encapsulate the pattern somehow. Sometimes this is a good idea, or sometimes it's fine to just leave the repetition, if the attempt to encapsulate it ends up making things worse.
One way to encapsulate this particular pattern — I'm not going to say whether I think it's a good way or not — would be to define a function-like macro:
#define INCR_MAX(var, max) if(var < max) var++
Then you could say
INCR_MAX(a, 10);
INCR_MAX(b, 100);
INCR_MAX(c, 1000);
One reason to want to make this a function-like macro (as opposed to a true function) is that a macro can "modify its argument" — in this case, whatever variable name you hand to it as var — in a way that a true function couldn't. (That is, if your saturating incrementer were a true function, you would have to call it either as incr_max(&a, 10) or a = incr_max(a, 10), depending on how you chose to set it up.)
However, there's an issue with function-like macros and the semicolon at the end. I'm not going to explain that whole issue here; there's a big long previous SO question about it.
Applying the lesson of that other question, an "improved" INCR_MAX macro would be
#define INCR_MAX(var, max) do { if(var < max) var++; } while(0)
Finally, it appears that somewhere between your exercise and this SO question, the while(0) at the end somehow got changed to while(1). This just about has to have been an unintentional error, since while(1) makes no sense in this context whatsoever.
Yeah, there's a reason you don't understand it - it's garbage.
After preprocessing, the code is
void main(void)
{
do
{
if ( 0 < 3 )
{
0++;
}
} while(1);
}
Yeah, no clue what this thing is supposed to do. The name MAX implies that it should evaluate to the larger of its two arguments, a la
#define MAX(a,b) ((a) < (b) ? (b) : (a))
but that's obviously not what it's doing. It's not defining an interval between two numbers, it's attempting to set the value of the first argument to the second, but in a way that doesn't make a lick of sense.
There are three problems (technically, four):
the compiler will yak on 0++ - a constant cannot be the operand of the ++ or -- operators;
If either i or limit are expressions, such as MAX(i+1, i+5) you're going to have the same problem with the ++ operator and you're going to have precedence issues;
assuming you fix those problems, you still have an infinite loop;
The (technical) fourth problem is ... using a macro as a function. I know, this is embedded world, and embedded world wants to minimize function call overhead. That's what the inline function specifier is supposed to buy you so you don't have to go through this heartburn.
But, okay, maybe the compiler available for the system you're working on doesn't support inline so you have to go through this exercise.
But you're going to have to go to the person who gave you this code and politely and respectfully ask, "what is this crap?"

Parenthesis do in C/Embedded C #define statements

I saw the following in a .h-file for the cc2640 mcu:
#define ADC_STATUS_SUCCESS (0)
From my C knowledge, the compiler is told to put the value of ADC_STATUS_SUCCESS everywhere it occurs, that is (0). But what is the difference in putting just 0?
what is the difference in putting just 0?
None, if you don't write crazy code. It is common to use parentheses for macros that contain expressions to avoid unexpected errors related to operator precedence and similar stuff when using them. In this case though, defining something as 0 or as (0) is the same if it's used in expressions.
What do I mean by "crazy code"? Well, the only difference between the two can be seen in something like the following:
void func(int x) { /* ... */ };
#define ADC_STATUS_SUCCESS 0
func ADC_STATUS_SUCCESS; // INVALID
#define ADC_STATUS_SUCCESS (0)
func ADC_STATUS_SUCCESS; // VALID (for the love of God NEVER do this)
I highly doubt this is the case though, nobody in their right mind would write such an abomination. That define is most likely out of habit.

Using if else in c macros

i'm trying to define the following macro:
#define UTF8_2B(c) if((0xc0 & c) == 0xc0){return 1;}
But i'm met with the error:
expected expression before ‘if’
The macro is called like so:
int i = UTF8_2B(c);
Where c is an unsigned char read from a file.
Why does this happen? Can you not use if else statements in macros?
Also, I've read that it's not a good idea to use semicolon in your macros, but i didn't understand why.
I'm new to c so the more thorough the answer the better.
C (and C++) preprocessor macros are essentially "copy-paste" with argument substitution. So your code becomes:
int i = if((0xc0 & c) == 0xc0){return 1;}
And this is invalid syntax.
You're assigning the result of your macro to a variable. You cannot do that with the current macro (return returns from the current function, and doesn't return something to be assigned to i: so not what you want).
If you're using gcc, you can view what your pre-processed code looks like with the -E command line.
So you can use if in macros, but not in macros that are used like functions, which are supposed to return a value.
Moreover:
if c is a complex expression, operator precedence could make the macro generate wrong code
the macro should provide a way to require semicolon, so IDEs and human readers see that as a normal function
I'd propose a simple test instead (which yields 1 if true, 0 otherwise), which meets the "need semicolon" standard and is safe to use with a complex c expression:
#define UTF8_2B(c) ((0xc0 & (c)) == 0xc0)
The ternary operator exists for this purpose. Assuming you want 1 if true and 0 if false, the correct macro is:
#define UTF8_2B(c) (((c) & 0xC0) == 0xC0 ? 1 : 0)
Now you can assign the result. Using return in a macro will return from the enclosing function, not from the macro, and is almost always a bad idea.

Legal uses of setjmp and GCC

Using GCC (4.0 for me), is this legal:
if(__builtin_expect(setjmp(buf) != 0, 1))
{
// handle error
}
else
{
// do action
}
I found a discussion saying it caused a problem for GCC back in 2003, but I would imagine that they would have fixed it by now. The C standard says that it's illegal to use setjmp unless it's one of four conditions, the relevant one being this:
one operand of a relational or equality operator with the other operand an integer constant expression, with the resulting expression being the entire controlling expression of a selection or iteration statement;
But if this is a GCC extension, can I guarantee that it will work under for GCC, since it's already nonstandard functionality? I tested it and it seemed to work, though I don't know how much testing I'd have to do to actually break it. (I'm hiding the call to __builtin_expect behind a macro, which is defined as a no-op for non-GCC, so it would be perfectly legal for other compilers.)
I think that what the standard was talking about was to account for doing something like this:
int x = printf("howdy");
if (setjmp(buf) != x ) {
function_that_might_call_longjmp_with_x(buf, x);
} else {
do_something_about_them_errors();
}
In this case you could not rely on x having the value that it was assigned in the previous line anymore. The compiler may have moved the place where x had been (reusing the register it had been in, or something), so the code that did the comparison would be looking in the wrong spot. (you could save x to another variable, and then reassign x to something else before calling the function, which might make the problem more obvious)
In your code you could have written it as:
int conditional;
conditional = setjump(buf) != 0 ;
if(__builtin_expect( conditional, 1)) {
// handle error
} else {
// do action
}
And I think that we can satisfy ourselves that the line of code that assigns the variable conditional meets that requirement.
But if this is a GCC extension, can I guarantee that it will work under for GCC, since it's already nonstandard functionality? I tested it and it seemed to work, though I don't know how much testing I'd have to do to actually break it. (I'm hiding the call to __builtin_expect behind a macro, which is defined as a no-op for non-GCC, so it would be perfectly legal for other compilers.)
You are correct, __builtin_expect should be a macro no-op for other compilers so the result is still defined.

What is the difference between if(CONST==variable) or if(variable==CONST)?

Is there a difference in the order of the comparison operator?
#define CONST_VALUE 5
int variable;
...
if ( variable == CONST_VALUE ) // Method 1
...
OR
if ( CONST_VALUE == variable ) // Method 2
...
Is this simply a matter of preference or is there a compelling reason for a particular comparison order?
The reason some people use method 2 is because you'll get a compiler error if you mistype a = in place of the ==.
However, you'll have people (like me) who will still use method 1 because they find it more readable and if there is an error, it will be detected during testing (or, in some cases, static analysis of the code).
The only difference is that ( CONST_VALUE == variable ) makes the common typo ( CONST_VALUE = variable ) impossible to compile.
By comparison, if ( variable = CONST_VALUE ) will result in the compiler thinking you meant to assign CONST_VALUE to 'variable'.
The =/== confusion is a pretty common source of bugs in C, which is why people are trying to work around the issue with coding conventions.
Of course, this won't save you if you're comparing two variables.
And the question seems to be a duplicate of How to check for equals? (0 == i) or (i == 0)
And here's some more information: http://cwe.mitre.org/data/definitions/481.html
As others mentioned, CONST_VALUE == variable avoids the = typo.
I still do "variable == CONST_VALUE", because I think its more readable and when I see something like:
if(false == somevariable)
my bloodpressure goes up.
The first variant
if (variable == CONST_VALUE)
is better, because it is more readable. It follows the convention (also used in mathematics) that the value that changes most comes first.
The second variant
if (CONST_VALUE == variable)
is used by some people to prevent a mixup of equality checking with the assignment
if (CONST_VALUE = variable)
There are better ways to achieve that, for example enabling and taking heed of compiler warnings.
Others already pointed out the reason. = / == confusion. I prefer the first version because it follows the thought process more closely. Some compiler alleviate the confusion of = and == by giving a warning when it encounters something like
if(a=b)
in this case if you really wanted to do the assignation you're forced to write
if((a=b))
which I would write then as
if( (a=b) != 0)
to avoid the confusion.
This said, we had in our code 1 case where we had a =/== confusion and writing it the other way round wouldn't not have aided as it was a comparison between vars.

Resources