Control flow


In software, control flow 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 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 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.

Sequence

Sequential execution is the most basic structure. Although not all code is sequential in nature, imperative code is.

Label

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.

void f

Block

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, control jumps from line 1 to 4 if done is false.

if else

Control

Many control commands have been devised for programming languages. This section describes notable constructs; it is organized by functionality.

Function

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, control returns to after the call, line 7.

void foo
void bar

Branch

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 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
else
writeln;

In C:

if else

In bash:

if ; then
echo "yes"
else
echo "no"
fi

In Python:

if a > 0:
print
else:
print

In Lisp:

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

In Bash:

case $someChar in
a) actionOnA ;;
x) actionOnX ;;
) actionOnYandZ ;;
*) actionOnNoMatch ;;
esac

In Lisp:



)

In Fortran:

select case
case
actionOnA
case
actionOnX
case
actionOnYandZ
case default
actionOnNoMatch
end select

Loop

A loop is a sequence of statements, loop body, which is executed a number of times based on runtime state. The body is executed once for each item of a collection, until a condition is met, or infinitely. A loop inside the loop body is called a nested loop. Early exit from a loop may be supported via a break statement.
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.
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
xxx
LOOP

Example in Pascal:

repeat
xxx
until test;

Example in C family of pre-test:

while

Example in C family of post-test:

do
xxx
while ;

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