In software, control flow (or flow of control) describes how execution progresses from one command to the next. In many contexts, such as machine code and an imperative programming language, control progresses sequentially (to the command located immediately after the currently executing command) except when a command transfers control to another point in which case the command is classified as a control flow command. Depending on context, other terms are used instead of command. For example, in machine code, the typical term is instruction and in an imperative language, the typical term is statement.
Although an imperative language encodes control flow explicitly, languages of other programming paradigms are less focused on control flow. A declarative language specifies desired results without prescribing an order of operations. A functional language uses both language constructs and functions to control flow even though they are usually not called control flow statements.
For a central processing unit instruction set, a control flow instruction often alters the program counter and is either an unconditional branch (a.k.a. jump) or a conditional branch. An alternative approach is predication which conditionally enables instructions instead of branching.
An asynchronous control flow transfer such as an interrupt or a signal alters the normal flow of control to a handler before returning control to where it was interrupted.
One way to attack software is to redirect the flow of execution. A variety of control-flow integrity techniques, including stack canaries, buffer overflow protection, shadow stacks, and vtable pointer verification, are used to defend against these attacks.
Structure Control flow is closely related to code structure. Control flows along lines defined by structure and the execution rules of a language. This general concept of structure is not be confused with structured programming which limits structure to sequencing, selection and iteration based on block organization.
Sequences Sequential execution is the most basic structure. Although not all code is sequential in nature, imperative code is.
Labels A label identifies a position in source code. Some control flow statements reference a label so that control jumps to the labeled line. Other than marking a position, a label has no other effect.
Some languages limit a label to a number which is sometimes called a line number, although that implies the inherent index of the line, not a label. None-the-less, such numeric labels are typically required to increment from top to bottom in a file even if not be sequential. For example, in BASIC:
10 LET X = 3 20 PRINT X 30 GOTO 10
In many languages, a label is an alphanumeric identifier, usually appearing at the start of a line and immediately followed by a colon. For example, the following C code defines a label on line 3 which identifies a jump target point at the first statement that follows it (line 4).
void f(bool ok) { if (ok) { goto success;
return; success: printf("OK"); }
Blocks Most languages provide for organizing sequences of code as a block. When used with a control statement, the beginning of a block provides a jump target. For example, in the following C code (which uses curly braces to delimit a block), control jumps from line 1 to 4 if done is false.
if (done) { printf("All done"); } else { printf("Still workin' on it"); }
Control
Many control commands have been devised for programming languages. This section describes notable constructs; it is organized by functionality.
Functions A function provides for control flow in that when called, execution jumps to the start of the function's code and when it completes, control returns the calling point. In the following C code, control jumps from line 6 to 2 in order to call function . Then, after completing the function body (printing "Hi"), control returns to after the call, line 7.
void foo() { printf("Hi"); }
void bar() { foo(); printf("Done"); }
Branches A branch command moves the point of execution from the point in the code that contains the command to the point that the command specifies.
Jump A jump command unconditionally branches control to another point in the code, and is the most basic form of controlling the flow of code.
In a high-level language, this is often provided as a goto statement. Although the keyword may be upper or lower case or one or two words depending on the language, it is like: goto label. When control reaches a goto statement, control then jumps to the statement that follows the indicated label. The goto statement has been considered harmful by many computer scientists, including Dijkstra.
Conditional branch A conditional statement jumps control based on the value of a Boolean expression. Common variations include:
if-goto Jumps to a label based on a condition; a high-level programming statement that closely mimics a similar used machine code instruction
if-then Rather than being restricted to a jump, a statement or block is executed if the expression is true. In a language that does not include the keyword, this can be called an if statement.
if-then-else Like if-then, but with a second action to be performed if the condition is false. In a language that does not include the keyword, this can be called an if-else statement.
Nested Conditional statements are often nested inside other conditional statements.
Arithmetic if Early Fortran, had an arithmetic if (a.k.a. three-way if) that tests whether a numeric value is negative, zero, or positive. This statement was deemed obsolete in Fortran-90, and deleted as of Fortran 2018.
Operator Some languages have an operator form, such as the ternary conditional operator.
When and unless Perl supplements a C-style with and .
Messages Smalltalk uses ifTrue and ifFalse messages to implement conditionals, rather than a language construct.
The following Pascal code shows a simple if-then-else. The syntax is similar in Ada:
if a > 0 then writeln("yes") else writeln("no");
In C:
if (a > 0) { puts("yes"); } else { puts("no"); }
In bash:
if [ $a -gt 0 ]; then echo "yes" else echo "no" fi
In Python:
if a > 0: print("yes") else: print("no")
In Lisp:
(princ (if (plusp a) "yes" "no"))
Multiway branch A multiway branch jumps control based on matching values. There is usually a provision for a default action if no match is found. A switch statement can allow compiler optimizations, such as lookup tables. In dynamic languages, the cases may not be limited to constant expressions, and might extend to pattern matching, as in the shell script example on the right, where the *) implements the default case as a glob matching any string. Case logic can also be implemented in functional form, as in SQL's decode statement.
The following Pascal code shows a relatively simple switch statement. Pascal uses the keyword instead of .
case someChar of 'a': actionOnA; 'x': actionOnX; 'y','z':actionOnYandZ; else actionOnNoMatch; end;
In Ada:
case someChar is when 'a' => actionOnA; when 'x' => actionOnX; when 'y' | 'z' => actionOnYandZ; when others => actionOnNoMatch; end;
In C:
switch (someChar) { case 'a': actionOnA; break; case 'x': actionOnX; break; case 'y': case 'z': actionOnYandZ; break; default: actionOnNoMatch; }
In Bash:
case $someChar in a) actionOnA ;; x) actionOnX ;; [yz]) actionOnYandZ ;; *) actionOnNoMatch ;; esac
In Lisp:
(case some-char ((#\a) action-on-a) ((#\x) action-on-x) ((#\y #\z) action-on-y-and-z) (else action-on-no-match))
In Fortran:
select case (someChar) case ('a') actionOnA case ('x') actionOnX case ('y','z') actionOnYandZ case default actionOnNoMatch end select
Loops
In a loop, a sequence of statements—frequently called the loop body—gets re-executed (at least in part) after a conditional branch or jump to a previous step in the sequence. The number of times a loop gets executed usually depends on runtime state, for example: the body is executed once for each item of a collection (definite iteration), until a condition is met (indefinite iteration). Some loops, on the other hand, may repeat infinitely. It is possible for a loop to be written as an infinite loop but for loop exit to be controlled by a test within the loop body that transfers control outside the loop. Early exit from a loop may be supported via a break statement.Roberts, E. "Loop Exits and Structured Programming: Reopening the Debate ," ACM SIGCSE Bulletin, (27)1: 268–272.
A loop inside the loop body of another loop is called a nested loop.
In a functional programming language, such as Haskell and Scheme, both recursive and iterative processes are expressed with tail recursive procedures instead of looping constructs that are syntactic.
Numeric
A relatively simple yet useful loop iterates over a range of numeric values. A simple form starts at an integer value, ends at a larger integer value and iterates for each integer value between. Often, the increment can be any integer value (even negative, to loop from a larger to a smaller value).
Example in BASIC:
FOR I = 1 TO N xxx NEXT I
Example in Pascal:
for I := 1 to N do begin xxx end;
Example in Fortran:
DO I = 1,N xxx END DO
In many programming languages, only integers can be used at all or reliably. As a floating-point number is represented imprecisely due to hardware constraints, the following loop might iterate 9 or 10 times, depending on various factors such as rounding error, hardware, compiler. Furthermore, if the increment of X occurs by repeated addition, accumulated rounding errors may mean that the value of X in each iteration can differ quite significantly from the commonly expected sequence of 0.1, 0.2, 0.3, ..., 1.0.
for X := 0.1 step 0.1 to 1.0 do
Condition-controlled
Some loop constructs iterate until a condition is true. Some variations test the condition at the start of the loop; others test at the end. If the test is at the start, the body may be skipped completely. At the end, the body is always executed at least once.
Example in Visual Basic:
DO WHILE (test) xxx LOOP
Example in Pascal:
repeat xxx until test;
Example in C family of pre-test:
while (test) { xxx }
Example in C family of post-test:
do xxx while (test);
Although using the keyword, the three-part C-style loop is a condition-based construct, not a numeric-based one. The second part, the condition, is evaluated before each loop, so the loop is pre-test. The first part is a place to initialize state, and the third part is for incrementing for the next iteration, but both aspects can be performed elsewhere. The following C code implements the logic of a numeric loop that iterates for i from 0 to n-1.
for (int i = 0; i < n; ++i) { xxx }
Enumeration
Some loop constructs enumerate the items of a collection; iterating for each item.
Example in Smalltalk:
someCollection do: [:eachElement |xxx].
Example in Pascal:
for Item in Collection do begin xxx end;
Example in Raku:
foreach (item; myCollection) { xxx }
Example in TCL:
foreach someArray { xxx }
Example in PHP:
foreach ($someArray as $k => $v) { xxx }
Example in Java:
Collection<String> coll; for (String s : coll) {}
Example in C#:
foreach (string s in myStringCollection) { xxx }
Example in PowerShell where 'foreach' is an alias of 'ForEach-Object':
someCollection | foreach { $_ }
Example in Fortran:
forall ( index = first:last:step... )
Scala has for-expressions, which generalise collection-controlled loops, and also support other uses, such as asynchronous programming. Haskell has do-expressions and comprehensions, which together provide similar function to for-expressions in Scala.
Infinite
Loop-and-a-half problem