CODE: C CPP Operators and Flow Control

At the heart of every C and C++ program lies a set of operators and flow-control mechanisms. Operators define what computation is performed, while flow control defines when and how often those computations execute.

Understanding both is essential—not just to write correct programs, but to write readable, efficient, and maintainable code, especially in systems programming, embedded development, and high-performance applications.

Operators in C and C++

In C and C++, operators are special symbols that instruct the compiler to perform specific operations on one or more operands (values or variables).

Operators are commonly classified in two ways:

  1. By arity – how many operands they require
  • _Unary_ (one operand)
  • _Binary_ (two operands)
  • _Ternary_ (three operands)
  1. By purpose – arithmetic, logical, bitwise, assignment, etc.

Let’s explore them category by category.


Arithmetic Operators

Arithmetic operators perform basic mathematical operations. They are among the most frequently used operators in any program.

Unary Arithmetic Operators

Unary operators act on a single operand.

  • + : Unary plus (rarely used explicitly)
  • - : Unary minus (sign inversion)
  • ++ : Increment
  • -- : Decrement

cpp
int a = 1;

// Prefix increment
int b = ++a;  // a = 2, b = 2

// Postfix increment
b = a++;      // a = 3, b = 2

Prefix vs Postfix Increment (Important Detail)

**Pre-increment (`++i`) is generally more efficient than post-increment (`i++`)**, especially for complex types (like iterators or user-defined classes).

Why? (Temp memory avoided)

  • i++ must create a temporary copy of the original value before incrementing.
  • ++i increments directly and returns the updated value.

For primitive types, the difference is often optimized away, but for iterators and objects, prefer prefix increment unless you explicitly need the old value.


Binary Arithmetic Operators

Binary arithmetic operators work on two operands.

  • + : Addition
  • - : Subtraction
  • * : Multiplication
  • / : Division
  • % : Modulus (remainder, integers only)

cpp
int x = 10;
int y = 3;

int sum = x + y;      // 13
int div = x / y;      // 3 (integer division!)
int mod = x % y;      // 1

**Integer division truncates toward zero**, which is a common source of bugs.

Comparison (Relational) Operators

Comparison operators compare two values and always produce a boolean result (true or false).

  • == : Equal to
  • != : Not equal to
  • > : Greater than
  • < : Less than
  • >= : Greater than or equal to
  • <= : Less than or equal to

cpp
int a = 5;
int b = 10;

bool result = (a < b); // true

These operators are the backbone of decision making and looping constructs.


Logical Operators

Logical operators combine or invert boolean expressions.

  • && : Logical AND
  • || : Logical OR
  • ! : Logical NOT

cpp
if (x > 0 && y > 0) {
    // both conditions must be true
}

Short-Circuit Evaluation

C and C++ use short-circuit evaluation:

  • A && B → if A is false, B is never evaluated
  • A || B → if A is true, B is never evaluated

This behavior is frequently used for safety checks (e.g., null-pointer validation).


Bitwise Operators

Bitwise operators operate directly on the binary representation of integers. They are heavily used in embedded systems, drivers, and performance-critical code.

  • & : Bitwise AND
  • | : Bitwise OR
  • ^ : Bitwise XOR
  • ~ : Bitwise NOT
  • << : Left shift (often equivalent to multiply by 2ⁿ)
  • >> : Right shift (often equivalent to divide by 2ⁿ)

cpp
unsigned int flags = 0b0010;
flags |= 0b0100;   // set a bit
flags &= ~0b0010;  // clear a bit

Shifts on signed integers can be implementation-defined, prefer unsigned types.

Assignment Operators

Assignment operators store values into variables.

Simple Assignment

  • = : Assign value

cpp
int x = 10;

Compound Assignment Operators

Compound operators combine an operation with assignment.

  • +=, -=, *=, /=, %=
  • &=, |=, ^=
  • <<=, >>=

cpp
int x = 5;
x += 3;  // x = 8
x <<= 1; // x = 16

These operators improve clarity and reduce repetition.


Preprocessor Operators

Used inside macros during preprocessing (before compilation).

  • # : Stringizing operator
  • ## : Token-pasting operator

c
#define TO_STRING(x) #x
#define CONCAT(a,b) a##b

These are powerful but should be used carefully due to readability and debugging complexity.


Operator Precedence

Operator precedence determines how expressions are grouped when parentheses are not explicitly used.

Operator TypeOperators
Parentheses()
Unary+, -, !, ~, ++, --
Multiplication / Division*, /, %
Addition / Subtraction+, -
Bitwise Shifts<<, >>
Bitwise AND / XOR / OR&, ^, `
Comparison<, <=, >, >=
Equality==, !=
Logical AND / OR&&, `
Ternary?:
Assignment=, +=, -=, etc.
Best practice: use parentheses to make intent explicit, even if precedence is known.

Flow Control in C and C++

By default, C and C++ programs execute sequentially, from top to bottom, starting in main().

Flow-control constructs allow you to branch, repeat, and alter execution paths based on conditions.

These mechanisms form the _decision-making logic_ of your program.


Conditional Execution

`if`, `else if`, `else`

cpp
int x = 7;

if (x > 10) {
    printf("x is greater than 10\n");
} else if (x > 5) {
    printf("x is greater than 5 but less than or equal to 10\n");
} else {
    printf("x is 5 or less\n");
}

Conditions must be enclosed in parentheses and evaluate to a boolean expression.


Ternary Operator (`?:`)

A compact alternative to simple if-else statements.

cpp
int a = 10;
int b = 20;

int max = (a > b) ? a : b;

Nested ternary expressions are possible but should be used with caution for readability:

cpp
int max = (x > y) ? ((x > z) ? x : z) : ((y > z) ? y : z);


`switch` Statement

Used for multi-branch selection based on integral or enum values.

cpp
int in = 0;

switch (in) {
    case 0:
        printf("Zero");
        break;
    case 1:
        printf("One");
        break;
    default:
        printf("Unknown");
}

Always include break unless intentional fall-through is desired.


Looping Constructs

`while` Loop

Repeats as long as the condition remains true.

cpp
while (keepgoing) {
    if (answer == 0) {
        break;
    }
    continue;
}


`do-while` Loop

Guarantees at least one execution.

cpp
int i = 0;
do {
    printf("i = %d\n", i);
    i++;
} while (i < 5);


`for` Loop

Traditional counted loop with three components:

  • Initialization
  • Condition
  • Increment

cpp
for (int loop = 0; loop < 10; loop++) {
    // ...
}


Range-Based `for` Loop (C++11)

Ideal for containers and arrays.

cpp
int arr[] = {1, 2, 3, 4};

for (int x : arr) {
    cout << x;
}


Jump Statements

Jump statements abruptly alter execution flow.

`break`

Exits loops or switch.

`continue`

Skips to the next iteration.

`goto` (Discouraged)

c
goto label;

While legal, goto often leads to unmaintainable code and should be avoided in modern C++.


Exception Handling (C++ Only)

C++ provides structured error handling using try, catch, and throw.

cpp
try {
    if (x < 0) {
        throw std::invalid_argument("Negative value not allowed");
    }
} catch (const std::exception& e) {
    std::cerr << e.what();
}

This mechanism separates error handling from normal logic, improving robustness.


`return` Statement

Terminates a function and optionally returns a value.

cpp
int add(int a, int b) {
    return a + b;
}

In main(), returning 0 typically indicates successful program termination.


Final Thoughts

Operators define what your program computes.

Flow control defines how and when it executes.

Mastering both is foundational to:

  • Writing correct logic
  • Avoiding subtle bugs
  • Understanding performance and execution flow
  • Progressing toward advanced C++ topics (RAII, templates, concurrency)

This knowledge forms the backbone of every serious C and C++ codebase.