I am looking at https://github.com/iputils/iputils/blob/s20161105/ping.c and I see from lines 608-713:
if (source.sin_addr.s_addr == 0) {
... // Omitted
} while(0);
Two questions:
How it compiles
What is the value of adding while (0) after if statement
It's two statements in succession. Entirely equivalent to this
if(/* ... */) {
// Body
}
while(0) {
// empty
}
while(0); is just a loop with a single empty statement for a body.
There is no value in adding it after the if. I suspect it's leftover from a previous refactoring, but the git history in that repository does not go that far.
It compiles because it is two statements, first
if (...) { ... }
followed by another statement
while (0);
i.e. a loop with empty body that is never run.
There is no value. while (0); as a separate statement is utterly useless. do { ... } while (0) is not useless but it is a completely different thing.
Probably the code was refactored from a form that initially used do { ... } while (0) and using breaks to exit the flow early (from the linked question above). Currently the source file does not have any instances of do statement, there are only 3 times that the verb do exists in some strings.
Related
I am trying to resolve warning issues which is shown as below :
warning: suggest braces around empty body in an 'if' statement
Relevant code:
cdc(.....)
{
//some statements
ENTER_FUNC(CDC_TRKEY_FC,cdcType_t); //Showing warning in this line
if(something)
{
if(..)
{
}
else
{
}
}
else
{
}
}
If I remove ; and adding the braces as below
ENTER_FUNC(CDC_TRKEY_FC,cdcType_t)
{
}
the warning is gone.
What does exactly it means? Is it behaving like an if statement?
Sorry, its confidential code, so I cant share entirely.
If this is your code
if (/* condition */);
/* other code */
Then the other code will ALWAYS be executed.
You probably want the other code to only be executed if the condition is true.
In order to achieve that, you mainly have to delete the ;.
It is widely considered to be best practice to be somewhat generous with the {}, i.e.
if (/* condition */)
{
/* other code */
}
The fact that the warning does not occur after deleting the ; in line
ENTER_FUNC(CDC_TRKEY_FC,cdcType_t); and replacing it with {}
can be explained if it is actually a macro which essentially expands (together with the ; which is NOT part of the macro) to the if();, which earlier versions of your question were mentioning.
The replacement with {} then does exactly what the compiler wanted.
The ENTER_FUNC() is probably meant to be used like
ENTER_FUNC(CDC_TRKEY_FC,cdcType_t) /* delete this ; */
{ /* new {, followed by rest of your function code */
if(something)
{
if(..)
{
}
else
{
}
}
else
{
}
} /* new */
Please excuse that this answer more or less assumes that you made a mistake in your code. Compare the contribution by Scheff, which assumes (also plausibly) that actually you were acting to a more complex design and fully intentionally.
The statement
if (cond) ; else do_something();
or even
if (cond) ; do_something();
might be intended. May be, the ; after if (cond) is a placeholder for something which shall be added later.
Inserting comments
if (cond) /** #todo */ ; else do_something();
or
if (cond) /** #todo */ ; /* and then always */ do_something();
would make it clear to the human reader but not for the compiler which ignores comments completely.
However, the compiler authors suspected high chance that the semicolon was unintendedly set (and can easily be overlooked). Hence, they spent a warning about this and gave a hint how to make the intention clear if there is one:
Use { } instead ; for intendedly empty then-body to come around this warning.
Sample:
#include <stdio.h>
int main()
{
int cond = 1;
if (cond) /** #todo */ ; else printf("cond not met.\n");
if (cond) /** #todo */ ; printf("cond checked.\n");
return 0;
}
Output:
cond checked.
Life demo on ideone
The compiler used on ideone is stated as gcc 6.3.
I must admit that I didn't get the diagnostics of OP.
After the question was edited, the answer does not seem to match the question anymore. Hence, a little update:
The OP states that the
warning: suggest braces around empty body in an 'if' statement
appears for this line of code:
ENTER_FUNC(CDC_TRKEY_FC,cdcType_t); //Showing warning in this line
It seems that the OP was not aware that ENTER_FUNC is (very likely) a macro with an if statement in its replacement text (something like #define ENTER_FUNC(A,B) if (...)). (This is the most imaginable scenario to get this warning for this code.)
Unfortunately, the OP is not willing to show how ENTER_FUNC is defined, nor to prepare an MCVE with the same behavior.
However, the technique to hide an if in a macro is even more questionable – I wouldn't recommend to do so. Imagine the following situation:
cdc(.....)
{
//some statements
ENTER_FUNC(CDC_TRKEY_FC,cdcType_t) // This time, the author forgot the ; or {}
if(something)
{
if(..)
{
}
else
{
}
}
else
{
}
}
The if(something) statement becomes now the body of the hidden if of the ENTER_FUNC() macro which is probably not intended but a bug. The application may now behave wrong in certain situations. By simply looking at the source code, this is probably hard to catch. Only, by single-step debugging and a bit luck, the error can be found.
(Another option would be to expand all macros and check the C code after replacement. C compilers provide usually a pre-process-only option which makes the result of pre-processing visible to human eyes. E.g. gcc -E)
So, the author of ENTER_FUNC built a macro which
causes a compiler warning if macro is used properly
where the warning goes away if macros is used wrong.
IMHO, this is a not-so-lucky design.
I am learning C and my question might be silly but im confused.In a function like:
int afunction(somevariables)
{
if (someconditions)
{
do some stuff
return 1;
}
raise_error("error happened")
return 0;
}
My question is,if the if statement isnt meeted(success),then it will go to the raise_error ? in other words,does the raise_errors position act like if it was in a else statement,or its because you have to return something at the end(return 0)?or would it need a proper else statement?Basically im confused on how to make a propre if condition--if this condition isnt meet--then call raise_error.
thank you!
if the if statement isn't met (success), then it will go to the raise_error?
Yes. When if condition is not met, the control is passed to else branch if it exists; otherwise, the entire if statement is skipped.
in other words, does the raise_errors position act like if it was in a else statement?
In this case, the answer is "yes", but only because your if branch is structured in a way that terminates the function due to return statement at the end.
Without that return at the end the control would go to raise_error upon completion of the if branch.
in other words,does the raise_errors position act like if it was in a else statement
Yes. Unless raise_error() does something that exits process, the return 0 will be executed aferwards.
Basically im confused on how to make a propre if condition--if this condition isnt meet--then call raise_error.
The code is fine. But if it makes it easier to understand then you can use an else clause too.
Your code is functionally equivalent to:
int afunction(somevariables)
{
if (someconditions) {
do some stuff
return 1;
}
else {
raise_error("error happened")
return 0;
}
}
The code or line that is not under some condition will always be executed unless you get out of the code before getting to that unconditional line. You don't need else in this case since you return 1 and does not execute remaining lines
I'm quite new to macros.
I know how to use if condition using ternary operator.
How do I convert this into a #define
if(i==j)
{
count=count+1;
break;
}
I try my luck with this but seems like it is wrong:
#define ifcount(i,j) ((i)==(j)? count=count+1\
break:0)
This is the code i'm trying to convert
http://pastebin.com/i7Tuyh00
Using (abusing) macros to change the flow of the program is usually a bad idea, because the people that will read your code (yourself in a few years) may get surprised by unexpected jumps in the program flow.
That said, your problem has nothing to do with the ternary operator. Actually the ternary operator cannot contain a break in its right side, only expressions.
But macros are allmighty, so you can just do:
#define ifcount(i,j) if ((i)==(j)) { count=count+1; break; }
The main problem with this macro is that people will write a ; when using it, and it will break badly if it is used between another if /else pair, without braces:
if (...)
ifcount(a,b);
else // <--- syntax error because the previous ; breaks the if /else relation
...;
The standard solution is to use the do/while(0) idiom:
#define do { ifcount(i,j) if ((i)==(j)) { count=count+1; break; } } while (0)
But that will not work because the break will break this inner while, not the one you want (credit to #abelenky) below.
The only other C statement that allows a compound statement and ends with a ; is this one:
#define ifcount(i,j) if ((i)==(j)) { count=count+1; break; } else
The problem is that if you forget to add the ; when using ifcount(i,j), instead of a compiler error you will get a silently compiling and surprisingly change in behavior.
I don't see any need to use the ternary (?:) operator.
So here is your macro using an if-statement.
#define IfCount(i,j) if ((i)==(j)) { count++; break; }
Usage:
IfCount(x,5);
Okay, what do you guys think of this?
#define IfCount(i,j) if ((i)==(j)) { count++; break; } do{}while(0)
The final, isolated do-while-0 serves a couple of purposes:
Its a place to hang a semi-colon, so the macro usage looks like "normal" C and ends with a semi-colon.
It prevents an inadvertent else-statement afterwards, because the syntax do{}while(0) else is invalid.
Is there anything else it should take care of?
if(turn==2)
{
if(forward) /*then what to do if this if comes true for coming out of outer loop*/
if(columnHead>0)
{
columnHead--;
addr[columnHead] |=1<<(rowHead-1);
}
else
{
columnHead =7;
addr[columnHead] |=1<<(rowHead-1);
}
if(rowTail!=(rowHead-1))
{
addr[columnHead+columnSize] &=~(1<<rowTail);
columnSize++;
rowTail++;
}
else
{
addr[columnTail] &=~(1<<columnTail);
if(columnTail==0)columnTail=8;
columnTail--;
}
back=1;
}
I want to come out of outer if loop if it satisfies condition if(forward)
You should create function of this code, and return from the block where the condition becomes true.
A standard idiom is to use while(true){/*your code here*/ break; } around the whole block and use break statements as appropriate which will take you to the end of the while brace. Just remember to include the final break or your program will loop.
Whatever you do, don't use a goto as they are considered very poor programming style.
Some folk, from the C days where while(true) would issue a compile warning, use for(;;) instead.
The odd thing is, thinking about this some more, you could use
do {
/*your code here, using break for premature exit*/
} while (false);
which doesn't need the final break. Only I've never seen this in production code.
I guess just putting an else in there will do what you want. Also, please put braces around big blocks - it makes the else part unambiguous.
if(turn==2)
{
if(forward) {
if(columnHead>0)
{
columnHead--;
addr[columnHead] |=1<<(rowHead-1);
}
else
{
columnHead =7;
addr[columnHead] |=1<<(rowHead-1);
}
} else {
if(rowTail!=(rowHead-1))
{
addr[columnHead+columnSize] &=~(1<<rowTail);
columnSize++;
rowTail++;
}
else
{
addr[columnTail] &=~(1<<columnTail);
if(columnTail==0)columnTail=8;
columnTail--;
}
back=1;
}
}
Version after the author's comment:
if(turn==2 && !forward) {
if(rowTail!=(rowHead-1))
{
addr[columnHead+columnSize] &=~(1<<rowTail);
columnSize++;
rowTail++;
}
else
{
addr[columnTail] &=~(1<<columnTail);
if(columnTail==0)columnTail=8;
columnTail--;
}
back=1;
}
You probably have to go the other direction, that means:
You don't want to check wether
if(forward) is true, but instead you want to do if(!forward).
Though you'd need to check what type forward is. I guess it's an integer though.
You can try giving the return 0; or return something; when you need to get out of the if, before that u may want to put the entire code in a c syntax function like-
(int)someFunction(int turn, int forward,
int columnHead, int rowHead, int rowTail, int columnTail)/*have all the arguments with proper types declaration*/{
//your code with return 0;
}.
why go into the "if" in the first place.
change the outter if to:
if(turn==2 && forward) //not sure if your logic required `forward` or `!forward` you were ambiguous
{
//...
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?
I met code like below:
#define ev_io_init(ev,cb,fd,events) \
do { \
ev_init ((ev), (cb)); \
ev_io_set ((ev),(fd),(events)); \
} while (0)
I want to know why the author use do { } while (0) here.
Is there any difference with this?
#define ev_io_init(ev,cb,fd,events) { \
ev_init ((ev), (cb)); \
ev_io_set ((ev),(fd),(events)); \
}
BTW: the code is from libev, ev_local.h
Consider if( something ) function1(); else function2();
If function1() is actually a macro, just using { } requires you to omit the semicolon at the point of use, but do { } while(0) lets you use exactly the same syntax as for a real function.
(Not using any kind of block construct at all would just generate completely broken code, natch)
Enclosing code with a loop allows for a preprocessor directive to execute multiple statements without "breaking" if-else-constructs. Consider the following:
#define DO_SOMETHING() a();b();c();
void foo()
{
// This is ok...
DO_SOMETHING();
}
void bar()
{
// ...whereas this would trigger an error.
if (condition)
DO_SOMETHING();
else
blah();
}
The second example breaks the if-else-construct because three statements are followed by an else clause. To allow for it to correctly substitute, the instructions in DO_SOMETHING should be enclosed with a do { ... } while(0).
A do{}while(0) allows you to break from the loop:
do{
expr1;
foo();
if ( cond )
break;
expr2;
goo();
} while (0);
It's the same as a simple block {...} except that you can break execution when you want with the break statement. You couldn't do that in a simple code block, unless you have multiple checks, which can get cumbersome. It still gets executed once, because of the condition while(0).