I'm currently trying to figure out a way to break out of a for
loop from within a function called in that loop. I'm aware of the possibility to just have the function return a value and then check against a particular value and then break, but I'd like to do it from within the function directly.
This is because I'm using an in-house library for a specific piece of hardware that mandates the function signature of my function to look like this:
void foo (int passV, int aVal, long bVal)
I'm aware that not using a return value is very bad practice, but alas circumstances force me to, so please bear with me.
Consider following example:
#include <stdio.h> void foo (int a) { printf("a: %d", a); break; } int main(void) { for (int i = 0; i <= 100; i++) { foo(i); } return 0; }
Now this does not compile. Instead, I get a compilation error as follows:
prog.c: In function 'foo': prog.c:6:2: error: break statement not within loop or switch break;
I know what this means (the compiler says that the break in foo()
is not within a for
loop)
Now, what I could find from the standard regarding the break statement is this:
The break statement causes control to pass to the statement following the innermost enclosing while, do, for, or switch statement. The syntax is simply break;
Considering my function is called from within a for
loop, why doesn't the break statement break out of said for loop? Furthermore, is it possible to realise something like this without having the function return first?
Breaking Out of For Loops. To break out of a for loop, you can use the endloop, continue, resume, or return statement. endfor; If condition is true, statementlist2 is not executed in that pass through the loop, and the entire loop is closed.
Using break , you can come out of the loop even if the condition for the end of the loop is not fulfilled. You cant have break because 'if /elif ' is not a loop, its just a conditional statement.
The purpose the break statement is to break out of a loop early. For example if the following code asks a use input a integer number x. If x is divisible by 5, the break statement is executed and this causes the exit from the loop.
Generally break statement breaks out of loops ( for , while , and do... while ) and switch statements.
You cannot use break;
this way, it must appear inside the body of the for
loop.
There are several ways to do this, but neither is recommended:
you can exit the program with the exit()
function. Since the loop is run from main()
and you do not do anything after it, it is possible to achieve what you want this way, but it as a special case.
You can set a global variable in the function and test that in the for
loop after the function call. Using global variables is generally not recommended practice.
you can use setjmp()
and longjmp()
, but it is like trying to squash a fly with a hammer, you may break other things and miss the fly altogether. I would not recommend this approach. Furthermore, it requires a jmpbuf
that you will have to pass to the function or access as a global variable.
An acceptable alternative is to pass the address of a status
variable as an extra argument: the function can set it to indicate the need to break from the loop.
But by far the best approach in C is returning a value to test for continuation, it is the most readable.
From your explanations, you don't have the source code for foo()
but can detect some conditions in a function that you can modify called directly or indirectly by foo()
: longjmp()
will jump from its location, deep inside the internals of foo()
, possibly many levels down the call stack, to the setjmp()
location, bypassing regular function exit code for all intermediary calls. If that's precisely what you need to do to avoid a crash, setjmp()
/ longjmp()
is a solution, but it may cause other problems such as resource leakage, missing initialization, inconsistent state and other sources of undefined behavior.
Note that your for
loop will iterate 101
times because you use the <=
operator. The idiomatic for
loop uses for (int i = 0; i < 100; i++)
to iterate exactly the number of times that appears as the upper (excluded) bound.
break
, like goto
, can only jump locally within the same function, but if you absolutely have to, you can use setjmp
and longjmp
:
#include <stdio.h> #include <setjmp.h> jmp_buf jump_target; void foo(void) { printf("Inside foo!\n"); longjmp(jump_target, 1); printf("Still inside foo!\n"); } int main(void) { if (setjmp(jump_target) == 0) foo(); else printf("Jumped out!\n"); return 0; }
The call to longjmp
will cause a jump back to the setjmp
call. The return value from setjmp
shows if it is returning after setting the jump target, or if it is returning from a jump.
Output:
Inside foo! Jumped out!
Nonlocal jumps are safe when used correctly, but there are a number of things to think carefully about:
longjmp
jumps "through" all the function activations between the setjmp
call and the longjmp
call, if any of those functions expect to be able to do additional work after the current place in execution, that work will simply not be done.setjmp
has terminated, the behaviour is undefined. Anything can happen.setjmp
hasn't yet been called, then jump_target
is not set, and the behaviour is undefined.setjmp
can under certain conditions have undefined values.setjmp
call.Most of these follow naturally if you have a good understanding of what a nonlocal jump does on the level of machine instructions and CPU registers, but unless you have that, and have read what the C standard does and does not guarantee, I would advise some caution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With