xSKILLby Infirals
Register

C for Beginners

0 of 24 notes read 0%

Reading progress is saved to your INFIRALS account. Sign in to keep this note marked as read.

Operators and decisions

Starting out11 min readLesson 4 of 5

4.1 Arithmetic operators

+, -, *, /, and % work on numbers. % is the remainder and accepts integers only.

Precedence follows the usual rules from maths: *, /, and % bind tighter than + and -. Parentheses override precedence, and adding them when a reader might pause costs nothing.

The increment operator ++ adds one, and -- subtracts one. count++ is a common statement in loops. ++count and count++ differ only when their value is used inside a larger expression, which is a place to slow down and add parentheses.

c
#include <stdio.h>

int main(void)
{
    int a = 7;
    int b = 2;
    int total = 11;

    printf("a * b + 3 = %d\n", a * b + 3);
    printf("a * (b + 3) = %d\n", a * (b + 3));
    printf("total / b = %d\n", total / b);
    printf("total %% b = %d\n", total % b);
    return 0;
}

Output

a * b + 3 = 17
a * (b + 3) = 35
total / b = 5
total % b = 1

4.2 Comparison and logic

Comparison operators produce 1 for true and 0 for false:

  • == equal to
  • != not equal to
  • <, >, <=, >= for ordering

A common beginner bug is writing if (x = 3) where if (x == 3) was meant. The first form assigns 3 and then tests the result, which is true, so the branch always runs. GCC and Clang warn about an assignment inside a condition.

Logical operators combine tests:

  • && is true when both sides are true
  • || is true when at least one side is true
  • ! flips true to false and false to true

&& and || short-circuit, so the right side is not evaluated when the result is already known. if (count != 0 && total / count > 2) avoids a division by zero for that reason.

c
#include <stdio.h>

int main(void)
{
    int age = 20;
    int has_ticket = 1;

    printf("age >= 18: %d\n", age >= 18);
    printf("age < 13: %d\n", age < 13);
    printf("both: %d\n", age >= 18 && has_ticket);
    printf("either: %d\n", age >= 18 || has_ticket);
    return 0;
}

Output

age >= 18: 1
age < 13: 0
both: 1
either: 1

4.3 The if statement

An if statement runs its block when the condition is nonzero. The optional else runs when the condition is zero. An else if chain tests conditions in order and stops at the first true one.

Indentation does not decide which if an else belongs to; braces do. Use braces even for a single statement, because a later edit that adds a second statement should not silently change which branch it belongs to.

A condition in C is any expression. Zero counts as false and every nonzero value counts as true. That is why if (1) is valid and why if (count) is a common shorthand for if (count != 0).

c
#include <stdio.h>

int main(void)
{
    int score = 84;

    if (score >= 90) {
        printf("Grade A\n");
    } else if (score >= 80) {
        printf("Grade B\n");
    } else if (score >= 70) {
        printf("Grade C\n");
    } else {
        printf("Keep going\n");
    }
    return 0;
}

Output

Grade B

4.4 The conditional operator

For two outcomes, C has a compact form: condition ? value_if_true : value_if_false. It is an expression, so it can sit on the right side of an assignment.

int larger = a > b ? a : b; reads as "if a is greater than b, use a, otherwise use b".

Use it when both results are short expressions. A chain of nested conditional operators is hard to read, and an if statement is clearer there.

c
#include <stdio.h>

int main(void)
{
    int a = 12;
    int b = 25;
    int larger = a > b ? a : b;
    int smaller = a < b ? a : b;

    printf("larger: %d\n", larger);
    printf("smaller: %d\n", smaller);
    printf("difference: %d\n", larger - smaller);
    return 0;
}

Output

larger: 25
smaller: 12
difference: 13

4.5 The switch statement

switch compares one integer expression against a list of case labels. Each label must be a constant that fits the switched type.

Control falls through from one case to the next until a break or the end of the block. Supply break unless the fall-through is deliberate, and add default to handle values you did not list.

switch works with int and char. It does not accept strings, because a string is an array and case labels must be integer constants.

c
#include <stdio.h>

int main(void)
{
    char command = 's';

    switch (command) {
        case 'n':
            printf("New file\n");
            break;
        case 's':
            printf("Save file\n");
            break;
        default:
            printf("Unknown command\n");
            break;
    }
    return 0;
}

Output

Save file

4.6 Mistakes to watch for

  • if (score = 60) assigns 60 and tests the result, so the branch runs for every nonzero assignment. Use == for a test.
  • if (score > 60); puts a semicolon right after the condition. The branch body is then an empty statement, and the next line runs whatever the score is.
  • & and | are bitwise operators, while && and || are logical ones. On plain 0 and 1 values the results often look alike, and they differ on other integers. The logical operators also short-circuit, and the bitwise ones do not.

GCC's -Wall warns about an assignment used as a condition, and -Wextra warns about the empty body.

c
#include <stdio.h>

int main(void)
{
    int score = 70;

    if (score > 90);                      /* empty statement */
    printf("This line always runs.\n");

    return 0;
}

Output

This line always runs.

Interview questions

3 questions from this note. Open one to see the answer; no account needed.

  • 01What is the difference between `=` and `==`?

    `=` assigns a value to a variable. `==` compares two values and produces `1` or `0`. Inside a condition, `if (x = 3)` assigns 3 and always takes the branch, while `if (x == 3)` tests it.

  • 02Why does C treat zero as false?

    C had no boolean type in its early versions, so conditions are integer expressions. Zero is false and every nonzero value is true. `<stdbool.h>` adds `bool`, `true`, and `false` as names for that behaviour.

  • 03When is `switch` a better choice than `if`?

    Use `switch` when one integer or character value selects among several fixed cases. Use `if` when the tests involve ranges, combined conditions, or other types.