What Are Compound Statements (Blocks)?

A compound statement, or block, is a group of zero or more statements enclosed in curly braces {} that the compiler treats as a single statement. Blocks define scope boundaries and are used throughout C++ in function bodies, loops, and conditionals.

A compound statement, also known as a block, is a collection of statements grouped together and treated by the compiler as if they were a single statement.

Blocks start with an opening brace {, end with a closing brace }, and contain zero or more statements in between. Unlike individual statements, blocks don't require a semicolon after the closing brace.

You've already encountered blocks when creating functions, since every function body is a block:

int calculateProduct(int width, int height)
{ // block begins
    return width * height;
} // block ends (note: no semicolon)

int main()
{ // block begins

    int result{42}; // this is initialization, not a block
    calculateProduct(7, 8);

    return 0;

} // block ends (note: no semicolon)

Nesting blocks within other blocks

While C++ doesn't allow you to define functions inside other functions, you can absolutely nest blocks inside other blocks:

int calculateProduct(int width, int height)
{ // block
    return width * height;
} // block ends

int main()
{ // outer block

    int result{42};

    { // inner/nested block
        calculateProduct(7, 8);
    } // inner/nested block ends

    return 0;

} // outer block ends

When you nest blocks, the outer block is referred to as the outer block while the block nested inside is called the inner block or nested block.

Executing multiple statements conditionally with blocks

Blocks are frequently used with conditional statements like if. By default, an if statement will only execute a single statement when its condition is true. However, by using a block, you can execute multiple statements when the condition evaluates to true.

Here's an example:

#include <iostream>

int main()
{ // outer block begins
    std::cout << "Please enter a number: ";
    int number{};
    std::cin >> number;

    if (number >= 0)
    { // nested block begins
        std::cout << number << " is non-negative\n";
        std::cout << "Triple this number is " << number * 3 << '\n';
    } // nested block ends
    else
    { // another nested block begins
        std::cout << number << " is negative\n";
        std::cout << "Its absolute value is " << -number << '\n';
    } // another nested block ends

    return 0;
} // outer block ends

If the user enters the number 7, the program outputs:

Please enter a number: 7 7 is non-negative Triple this number is 21

If the user enters the number -12, the program outputs:

Please enter a number: -12 -12 is negative Its absolute value is 12

Understanding nesting levels

You can nest blocks within blocks within blocks, creating multiple levels of nesting:

#include <iostream>

int main()
{ // block 1, nesting level 1
    std::cout << "Enter a number: ";
    int number{};
    std::cin >> number;

    if (number > 0)
    { // block 2, nesting level 2
        if ((number % 3) == 0)
        { // block 3, nesting level 3
            std::cout << number << " is positive and divisible by 3\n";
        }
        else
        { // block 4, also nesting level 3
            std::cout << number << " is positive but not divisible by 3\n";
        }
    }

    return 0;
}

The nesting level (sometimes called nesting depth) represents the maximum number of nested blocks you can be inside simultaneously at any point in your code (including the outermost block). In the example above, we have 4 distinct blocks, but the nesting level is 3 since you can never be inside more than 3 blocks at the same time.

The C++ standard requires compilers to support at least 256 levels of nesting, though not all compilers fully support this limit (for instance, some versions of Visual Studio support fewer levels).

It's best practice to keep your nesting level at 3 or fewer. Just as extremely long functions should be broken down into smaller ones, deeply nested blocks make code difficult to read and should be refactored (typically by extracting the deeply nested code into separate functions).

Best Practice
Keep the nesting level of your functions to 3 or less. If you need deeper nesting, consider refactoring your code by extracting nested blocks into separate functions.

Summary

  • Compound statement/block: A group of statements enclosed in braces { } and treated as a single statement by the compiler
  • No semicolon needed: Unlike individual statements, blocks don't require a semicolon after the closing brace
  • Function bodies: Every function body is a block
  • Nested blocks: Blocks can be nested inside other blocks; the containing block is the outer block, the enclosed block is the inner/nested block
  • Conditional execution: Blocks are commonly used with if statements to execute multiple statements when a condition is true
  • Nesting level: The maximum number of nested blocks you can be inside simultaneously (including the outermost block)
  • Compiler support: The C++ standard requires compilers to support at least 256 levels of nesting
  • Best practice limit: Keep nesting level to 3 or fewer for readability
  • Refactoring deep nesting: Extract deeply nested code into separate functions to improve readability

Blocks are fundamental to C++ control flow, allowing you to group multiple statements together for conditional execution or function definitions. While the compiler supports deep nesting, keeping nesting levels shallow (3 or less) makes code more readable and maintainable.