Unreachable code in for loop increment? - c++

I'm getting a C4702: unreachable code warning in a for loop; the strange thing is that - by breaking apart the components inside the parens - the warning points to the increment part. Here's a sample program that demonstrates this error:
int main()
{
int foo = 3;
for (int i = 0;
i < 999;
i++) // warning on this line
{
if (foo == 4);
{
break;
}
}
return 0;
}
I can't figure out what's wrong with this line, because the for loop looks very straight-forward.

You have a stray semicolon in your if-statement:
if (foo == 4);
Recall that for loops have the following structure:
for (initialisation; condition; increment/decrement)
statement
Execution will proceed in the following order:
initialisation
condition; if false then end
statement
increment/decrement
Go to step 2
If the compiler is warning about the increment/decrement being unreachable, it means that something before it is causing execution to always skip it - in this case, the stray semicolon causes the break to always execute, jumping out of the loop prematurely.

for (int i = 0;
i < 999;
i++) // warning on this line
{
if (foo == 4);
{
break;
}
}
This is same as
for (int i = 0;
i < 999;
)
{
if (foo == 4);
{
break;
}
i++; /* Note the increment here */
}
So anyways you are going to break because of the if(foo == 4); so i++ is not reachable

The problem (i.e. the unintended ;) is already described in two answers.
I just like to add that you should take a look at your compiler options setting. Many compilers can detect such "strange looking" code and give you a warning. For instance:
Warning: "empty body in an 'if' statement"
Further the compiler can be configured to treat all warnings as errors.
In other words - the compiler options can often help you finding "unintended code" so that you avoid wasting time.
BTW - the eclipse editor can even give a "suspicious semicolon" warning as soon as you type such an if-statement.

Related

Why does a for loop invoke a warning when using identical code?

I think that following two codes are identical. but upper one has C4715 "not all control paths return a value" problem and other doesn't.
Why this warning happens?
int func(int n){
for(int i=0; i<1; i++){
if(n == 0){
return 0;
}
else {
return -1;
}
}
}
int func(int n){
if(n == 0){
return 0;
}
else {
return -1;
}
}
The compiler is trying to be helpful, and failing. Pretend for a moment that the code inside the loop was just if (n == 0) return 0;. Clearly, when n is not 0, the loop will execute once and then execution will move on to the next statement after the loop. There's no return statement there, and that's what the compiler is warning you about. It just isn't smart enough to see that the code inside the loop always returns.
So, possibly, add a return 0; statement after the loop. That might make the compiler happy. But it also might make the compiler (or some other compiler) give a different warning about "unreachable code", because that new return statement can't actually be reached. This stuff is hard to analyze, and compilers often get it wrong.
Because warnings don't promise to only flag incorrect code. Nor do they promise to flag all incorrect code. It's not possible to be completely accurate.
It seems like the part of the compiler that issues C4715 assumes that a for loop with an end condition ends in some cases, and doesn't try to calculate if it will always return early.
My first thought is that the loop cannot act.
You initialize the for loop with int i = 0 then give bounds of i < 1 with an action if i++
Given i is type int with step of 1, it can never loop.

Is the Break keyword the most efficent way to exit a for loop? C/C++

Is break the most efficient way to exit a loop? In the code snippet below, would line A or line B be the more efficient way to exit the loop? Any links to material on how the break instruction works under the hood would be appreciated.
for (int i = 0; i < 10; i++) {
cout << i << endl;
if (i == 3) {
break; // A
i = 15; // B
}
}
I assume the difference is trivial in most situations, and that A is faster because B requires an assignment, an increment, and then a comparison, but I don't actually know how break works and it's better to know than assume. Thanks!
Let's compile the following code and look at the assembly:
#include <stdio.h>
int loop_with_break() {
for (int i = 0; i < 10; i ++) {
puts("Hello, world!");
if (i == 3) {
break;
}
}
}
int loop_with_assignment() {
for (int i = 0; i < 10; i ++) {
puts("Hello, world!");
if (i == 3) {
i = 10;
}
}
}
int main() {
loop_with_break();
loop_with_assignment();
}
As you can see, when you use break, if i == 3, it'll jump straight out of the loop to the end of the function, whereas if you use i = 10, it'll set i to 10, increment it by 1, then do the comparison, which is slower. However, this was compiled with no optimizations. If you use optimizations, they both end up becoming the same thing. However, since break is more readable and these optimizations are not guaranteed, you should use it for breaking out of loops.
The keyword break will just quit the loop without any comparison made in the loop condition. If you use i = 15 syntax, the loop will iterate next time to verify whether the variable i is greater than 10, if so, then quit.
In short words, break will break the loop without thinking anything, whereas i = 15 will lead one more iteration to look if the condition satisfies it.
You're right! Actually break keyword is very faster for breaking loop!
In your example, if you use line A, then as soon as control reaches this statement, it will immediately break the loop.
On the other hand, if you use line B, then first the assignment will be performed and again the control will go to the condition checking and when the condition will get false then it will exit from the loop!
if you choose while loop you can prefer to make condition false in the while loop. But in this case using break make sense.

c++ for loop: 'i' was not declared in this scope

bool linear_search(const string A[], int n, string colour, int &count)
{
for (int i = 0; i < n; i++);
{
if (colour == A[i])
{
return true;
}
}
return false;
}
Compiling the above code results in the error 'i' was not declared in this scope for the if statement if (colour == A[i]).
This is really similar to many other for loops I have written, and I don't understand why it is not declared in the scope. Wasn't it declared in the previous line? How do I fix this?
You have a semi colon after your for loop declaration, remove it and you will be fine.
As others have pointed out, the problem is an extra semicolon that prevents your intended loop body from actually being part of the loop. But I want to provide more information on how to catch and avoid this kind of error.
First of all, when I compile the code with the formatting you show, my compiler produces a warning:
main.cpp:130:32: warning: for loop has empty body [-Wempty-body]
for (int i = 0; i < n; i++);
^
You should check to see if you're already getting this or some similar warning, and if so you should make sure to pay attention to warnings in the future. If you're not getting this warning, see if you can increase your compiler's warning level in some way to cause it to produce a warning like this. Enabling and paying attention to compiler warnings can save you a lot of trouble.
Next, I notice that your code is poorly formatted. Poor formatting can hide this sort of error. When I auto-format the code it becomes:
bool linear_search(const string A[], int n, string colour, int &count) {
for (int i = 0; i < n; i++)
;
{
if (colour == A[i]) {
return true;
}
}
return false;
}
This formatting makes the extraneous semicolon much more obvious. (It also suppresses my compiler's warning about the empty body, since the compiler assumes that if you put the empty body on a separate line then you really mean for it to be empty.) Using automatic formatting avoids the problems of inconsistent formatting and ensures that the formatting is consistent with the actual meaning of the code. See if your editor provides formatting support or see if you can integrate an external formatter like clang-format.
Are you sure you need ; in this line? for (int i = 0; i < n; i++);
you ended for loops block by adding a ; after for loop
for (int i = 0; i < n; i++);
remove this semicolon.
I had a similar problem but there was an "if" statement before my variable declaration in front of a "for" loop, the error was the same. Just in case that somebody googled it and didn't mention something like that:
if (someVar!=1) // an "if" statement that reduces the scope of "var"
//some comment line
//some other comment line
double var = 0.0;
for (size_t i = 0; i < length; i++) {
var *= 0.5; // Error appeared here
}

CodeBlocks Breakpoints Ignoring Scope

I set a breakpoint inside a conditional statement that checks for a certain value of a custom datatype. The game will break, but the line it breaks on is completely outside of my breakpoint's scope. Watch variables reveal that it just breaks the first time that loop is iterated through, rendering my debugging conditional statement absolutely useless.
In Visual Studio, the debugger would respect scope, and placing a breakpoint inside a conditional statement would only stop the game if that conditional evaluated to true. Why is this not the case with the GDB debugger in CodeBlocks? Is it because I'm using GDB in Windows? Here's the code:
for(int j = 0 ; j < r->components[i].size() ; j++)
{
itype_id type = r->components[i][j].type;
int req = r->components[i][j].count;
//DEBUGGING ONLY!!!!!!!!!
if(type == itm_coffee_raw)
{
int pleaseStop = 0;
if(pleaseStop == 0) //BREAKPOINT IS ON THIS LINE
bool dontstoptillyougetenough = true;
}
if (itypes[type]->count_by_charges() && req > 0) //GAME BREAKS HERE
{
if (crafting_inv.has_charges(type, req))
{
has_comp = true;
break;
}
}
else if (crafting_inv.has_amount(type, abs(req)))
{
has_comp = true;
break;
}
}
The code inside the if body doesn't really do anything, so the compiler could see it as "dead code" and remove it from the executable in an optimization pass. This means that the code in question doesn't actually exist in the final executable, and so you can't put a breakpoint there.
Turn off optimizations (always good when debugging in general) and it should work.

Why are empty expressions legal in C/C++?

int main()
{
int var = 0;; // Typo which compiles just fine
}
How else could assert(foo == bar); compile down to nothing when NDEBUG is defined?
This is the way C and C++ express NOP.
You want to be able to do things like
while (fnorble(the_smurf) == FAILED)
;
and not
while (fnorble(the_smurf) == FAILED)
do_nothing_just_because_you_have_to_write_something_here();
But! Please do not write the empty statement on the same line, like this:
while (fnorble(the_smurf) == FAILED);
That’s a very good way to confuse the reader, since it is easy to miss the semicolon, and therefore think that the next row is the body of the loop. Remember: Programming is really about communication — not with the compiler, but with other people, who will read your code. (Or with yourself, three years later!)
I'm no language designer, but the answer I'd give is "why not?" From the language design perspective, one wants the rules (i.e. the grammar) to be as simple as possible.
Not to mention that "empty expressions" have uses, i.e.
for (i = 0; i < INSANE_NUMBER; i++);
Will dead-wait (not a good use, but a use nonetheless).
EDIT: As pointed out in a comment to this answer, any compiler worth its salt would probably not busy wait at this loop, and optimize it away. However, if there were something more useful in the for head itself (other than i++), which I've seen done (strangely) with data structure traversal, then I imagine you could still construct a loop with an empty body (by using/abusing the "for" construct).
OK, I’ll add this to the worst case scenario that you may actually use:
for (int yy = 0; yy < nHeight; ++yy) {
for (int xx = 0; xx < nWidth; ++xx) {
for (int vv = yy - 3; vv <= yy + 3; ++vv) {
for (int uu = xx - 3; uu <= xx + 3; ++uu) {
if (test(uu, vv)) {
goto Next;
}
}
}
Next:;
}
}
I honestly don't know if this is the real reason, but I think something that makes more sense is to think about it from the standpoint of a compiler implementer.
Large portions of compilers are built by automated tools that analyze special classes of grammars. It seems very natural that useful grammars would allow for empty statements. It seems like unnecessary work to detect such an "error" when it doesn't change the semantics of your code. The empty statement won't do anything, as the compiler won't generate code for those statements.
It seems to me that this is just a result of "Don't fix something that isn't broken"...
Obviously, it is so that we can say things like
for (;;) {
// stuff
}
Who could live without that?
When using ;, please also be aware about one thing. This is ok:
a ? b() : c();
However this won't compile:
a ? b() : ; ;
There are already many good answers but have not seen the productive-environment sample.
Here is FreeBSD's implementation of strlen:
size_t
strlen(const char *str)
{
const char *s;
for (s = str; *s; ++s)
;
return (s - str);
}
The most common case is probably
int i = 0;
for (/* empty */; i != 10; ++i) {
if (x[i].bad) break;
}
if (i != 10) {
/* panic */
}
while (1) {
; /* do nothing */
}
There are times when you want to sit and do nothing. An event/interrupt driven embedded application or when you don't want a function to exit such as when setting up threads and waiting for the first context switch.
example:
http://lxr.linux.no/linux+v2.6.29/arch/m68k/mac/misc.c#L523