I SEMESTER · C PROGRAMMING · UNIT 02

Read input.
Control the flow.

Work with values. Make decisions.
Understand every iteration.

Complete Unit 2 syllabus7 interactive demonstrations17 runnable programs10 self-check questions

UNIT 02 · 01

Tell C what to read. Choose how to display it.

printf() writes formatted output to standard output. scanf() converts input from standard input and stores it in objects. Both are declared in <stdio.h>. Their first argument is a format string (also called a control string): ordinary characters plus conversion specifications beginning with %.

printf("Roll: %d, marks: %.2f\n", roll, marks);
scanf("%d %lf", &roll, &marks);

In printf, pass values. In scanf, pass addresses of objects with the correct types. The & operator supplies an address; a character array already converts to a pointer to its first element. A mismatched conversion and argument can cause undefined behaviour.

Conversionprintf argument / effectscanf destination
%dint, signed decimalint *
%uunsigned int, unsigned decimalunsigned int *
%fdouble, fixed-point displayfloat *
%lfUse %f for double in the C90 examples heredouble *
%cint containing a characterchar *
%sPointer to a null-terminated character sequencechar array with enough space; stops at whitespace
%%Print one literal %; consumes no argumentMatch a literal %; makes no assignment

Width, precision and successful input

  • %6d uses a minimum width of six characters; %06d pads with zeros. Width does not cut off a longer result.
  • %.2f displays two digits after the decimal point. %8.2f combines width and precision; %-8.2f aligns left.
  • scanf returns the number of successful assignments. Check it before using the variables: if (scanf("%d %lf", &roll, &marks) != 2).
  • For char name[20], use scanf("%19s", name) to leave room for the final null character. This reads one word, not a full name with spaces.
  • Most conversions skip leading whitespace. %c does not. Use " %c" to skip whitespace before reading a non-whitespace character.
  • Whitespace in a scanf format matches any amount of input whitespace. A trailing \n can keep interactive input waiting for another non-whitespace character; it is not a command to read exactly one newline.

EXPLORE THE CONCEPT

See the padding and precision

42

An integer without extra padding.

Dots in this demonstration represent spaces so you can see the field width.

Formatted input and outputmain.c
#include <stdio.h>
int main(void)
{
    int roll;
    double marks;
    if (scanf("%d %lf", &roll, &marks) != 2) {
        puts("Enter a roll number and marks.");
        return 1;
    }
    printf("Roll: %03d\n", roll);
    printf("Marks: %.2f\n", marks);
    printf("Completion: 100%%\n");
    return 0;
}
EXPECTED OUTPUTRoll: 007 Marks: 85.50 Completion: 100%

Try this program
scanf and the newline trapmain.c
#include <stdio.h>
int main(void)
{
    int count;
    char code;
    if (scanf("%d", &count) != 1 || scanf(" %c", &code) != 1) {
        puts("Enter a count and a character.");
        return 1;
    }
    /* The space before %c skips whitespace, including newline. */
    printf("Count = %d\nCode = %c\n", count, code);
    return 0;
}
EXPECTED OUTPUTCount = 4 Code = A

Try this program

Escape sequences

An escape sequence represents a character within a string or character constant. It is interpreted by C before the library handles the string. %% is a printf conversion, not a backslash escape.

SequenceMeaning
\nNewline
\tHorizontal tab; display depends on tab stops
\bBackspace; terminal behaviour varies
\rCarriage return; terminal behaviour varies
\\Backslash
\"Double quote
\'Single quote
\0Null character, value zero; ends a C string, not a printed digit 0

UNIT 02 · 02

One character. One line.

“Unformatted” I/O transfers characters or strings without conversion specifications. These functions also belong to <stdio.h>.

FunctionWhat it doesRemember
getchar()Reads the next character from stdinReturns int: a character value or EOF. Store it in int before testing EOF.
putchar(ch)Writes one character to stdoutReturns the written character as int, or EOF on failure.
puts(text)Writes a string to stdoutAdds a newline; does not print the terminating null character.
gets(buffer)Legacy input of a line, without its newlineHas no buffer-size argument. It cannot prevent overflow and was removed from C11.
fgets(buffer, size, stdin)Reads at most size − 1 characters and appends a null character on successMay retain the newline. A long line can remain partly unread; NULL indicates failure/end before any characters.

Recognize gets() in the syllabus

The historical call is gets(buffer);. Explain its purpose in an exam, then state its lack of bounds checking. For runnable programs use fgets(buffer, sizeof buffer, stdin). Checking its return value is still necessary. Removing the newline is a separate step.

getchar and putcharmain.c
#include <stdio.h>
int main(void)
{
    int ch = getchar();
    if (ch == EOF) {
        puts("No character was supplied.");
        return 1;
    }
    printf("Character: ");
    putchar(ch);
    putchar('\n');
    return 0;
}
EXPECTED OUTPUTCharacter: A

Try this program
Read a line with fgets and print with putsmain.c
#include <stdio.h>
#include <string.h>
int main(void)
{
    char line[40];
    if (fgets(line, sizeof line, stdin) == NULL) {
        puts("No line was supplied.");
        return 1;
    }
    /* Remove the newline if fgets stored one. */
    line[strcspn(line, "\n")] = '\0';
    puts("You typed:");
    puts(line);
    return 0;
}
EXPECTED OUTPUTYou typed: BCA study desk

Try this program

UNIT 02 · 03

Calculate a value. Test a condition.

Operators act on operands to produce values. Integer and floating-point operands can produce different results even with the same operator.

FamilyOperatorsExample and result
Arithmetic+ − * / %7 / 2 → 3; 7 % 2 → 1; 7.0 / 2 → 3.5
Relational / equality< <= > >= == !=8 > 2 → 1; 8 == 2 → 0
Logical&& || !(8 > 2) && (2 > 0) → 1

Conditions treat zero as false and any nonzero value as true. Relational, equality and logical operators return int values 0 or 1. The remainder operator % requires integer operands. Division or remainder by zero is undefined; signed overflow is also undefined. For integer division, C99 and later truncate toward zero; C90 had implementation-defined rounding when a operand was negative. Our introductory arithmetic example uses nonnegative values.

Short-circuit evaluation

&& evaluates its right operand only if its left operand is true. || evaluates its right operand only if its left operand is false. This allows a guard such as b != 0 && a / b > 2. Bitwise & and | do not provide this guard.

Arithmetic: integer and floating divisionmain.c
#include <stdio.h>
int main(void)
{
    int a, b;
    if (scanf("%d %d", &a, &b) != 2 || a < 0 || a > 100 || b < 1 || b > 100) {
        puts("Enter a from 0 to 100 and b from 1 to 100.");
        return 1;
    }
    printf("Add = %d\n", a + b);
    printf("Subtract = %d\n", a - b);
    printf("Multiply = %d\n", a * b);
    printf("Integer division = %d\n", a / b);
    printf("Remainder = %d\n", a % b);
    printf("Floating division = %.2f\n", (double)a / b);
    return 0;
}
EXPECTED OUTPUTAdd = 9 Subtract = 5 Multiply = 14 Integer division = 3 Remainder = 1 Floating division = 3.50

Try this program
Relational, logical and short-circuit testsmain.c
#include <stdio.h>
int main(void)
{
    int a, b;
    if (scanf("%d %d", &a, &b) != 2 || a < 0 || a > 100 || b < 0 || b > 100) {
        puts("Enter two integers from 0 to 100.");
        return 1;
    }
    printf("a > b: %d\n", a > b);
    printf("a == b: %d\n", a == b);
    printf("Both positive: %d\n", a > 0 && b > 0);
    printf("At least one positive: %d\n", a > 0 || b > 0);
    printf("a is zero: %d\n", !a);
    /* If b is zero, && skips a / b. */
    printf("Safe quotient exceeds 2: %d\n", b != 0 && a / b > 2);
    return 0;
}
EXPECTED OUTPUTa > b: 1 a == b: 0 Both positive: 1 At least one positive: 1 a is zero: 0 Safe quotient exceeds 2: 1

Try this program

UNIT 02 · 04

Change the variable. Track the result.

= stores a value; == compares values. Compound assignment combines an operation and assignment: x += 3 adds three to x. More generally, the left operand of a compound assignment is evaluated once, which matters when it is a complex expression.

OperatorSimple-variable meaning
+= -= *= /= %=Add, subtract, multiply, divide or take remainder, then assign
&= |= ^=Apply a bitwise operation, then assign
<<= >>=Shift, then assign
Compound assignmentmain.c
#include <stdio.h>
int main(void)
{
    int x = 5;
    printf("Start: %d\n", x);
    x += 3; printf("After += 3: %d\n", x);
    x *= 2; printf("After *= 2: %d\n", x);
    x -= 1; printf("After -= 1: %d\n", x);
    x /= 3; printf("After /= 3: %d\n", x);
    x %= 2; printf("After %%= 2: %d\n", x);
    return 0;
}
EXPECTED OUTPUTStart: 5 After += 3: 8 After *= 2: 16 After -= 1: 15 After /= 3: 5 After %= 2: 1

Try this program

Prefix and postfix

Both ++ and -- change a modifiable operand by one. Prefix produces the updated value; postfix produces the old value and updates the operand. When used as a statement by itself, ++x; and x++; have the same final effect on x.

EXPLORE THE CONCEPT

One update at a time

Value of expression 5x after statement 6

Postfix produces the old value, then x becomes 6.

Prefix and postfix, one statement at a timemain.c
#include <stdio.h>
int main(void)
{
    int x = 5, value;
    value = x++;
    printf("Postfix: old = %d, x = %d\n", value, x);
    value = ++x;
    printf("Prefix: new = %d, x = %d\n", value, x);
    value = x--;
    printf("Post-decrement: old = %d, x = %d\n", value, x);
    value = --x;
    printf("Pre-decrement: new = %d, x = %d\n", value, x);
    return 0;
}
EXPECTED OUTPUTPostfix: old = 5, x = 6 Prefix: new = 7, x = 7 Post-decrement: old = 7, x = 6 Pre-decrement: new = 5, x = 5

Try this program

Avoid unsequenced updates

Do not predict a fixed answer for expressions such as i++ + ++i or printf("%d %d", i++, i++). They modify the same scalar object without the required sequencing and have undefined behaviour. Put updates in separate statements when learning or writing clear code.

UNIT 02 · 05

Look at the individual bits.

Bitwise operators work with integer operands. & keeps a bit when both inputs have it; | keeps it when either has it; ^ keeps it when the inputs differ. ~ complements bits, while << and >> shift positions.

EXPLORE THE CONCEPT

Explore the low eight bits

This visualizer displays the low eight bits. C’s unsigned int can be wider than eight bits. Shifts show the full decimal result as well as its low eight bits.

Use unsigned operands for simple bit operations. A shift count must be nonnegative and less than the width of the promoted left operand. Signed left shifts can be undefined; right-shifting a negative signed value is implementation-defined in the C versions covered here. The example masks a complement with 255U to display only the low eight bits.

Bitwise operators with unsigned valuesmain.c
#include <stdio.h>
int main(void)
{
    unsigned int a, b;
    if (scanf("%u %u", &a, &b) != 2 || a > 255U || b > 255U) {
        puts("Enter two unsigned values from 0 to 255.");
        return 1;
    }
    printf("AND = %u\n", a & b);
    printf("OR = %u\n", a | b);
    printf("XOR = %u\n", a ^ b);
    printf("NOT a (low 8 bits) = %u\n", (~a) & 255U);
    printf("Left shift by 1 = %u\n", a << 1);
    printf("Right shift by 1 = %u\n", a >> 1);
    return 0;
}
EXPECTED OUTPUTAND = 8 OR = 14 XOR = 6 NOT a (low 8 bits) = 243 Left shift by 1 = 24 Right shift by 1 = 6

Try this program

UNIT 02 · 06

Select, convert and inspect.

The conditional operator has three operands: condition ? value_if_true : value_if_false. It evaluates the condition and only the selected second or third operand. Compatible operand types determine the result type; it is an expression, so its value can be assigned or printed.

Conditional operator: maximummain.c
#include <stdio.h>
int main(void)
{
    int a, b, maximum;
    if (scanf("%d %d", &a, &b) != 2) {
        puts("Enter two integers.");
        return 1;
    }
    maximum = a > b ? a : b;
    printf("Maximum = %d\n", maximum);
    return 0;
}
EXPECTED OUTPUTMaximum = 20

Try this program
Operator / constructPurposeExample
sizeofSize in bytes; result type is size_t. For ordinary non-VLA operands it does not evaluate the operand.sizeof x; no universal fixed size for int
Cast (type)Explicit type conversion(double)5 / 2 → 2.5
Address &Address of an objectp = &x
Indirection *Access the object pointed to*p; pointer must be valid
Comma ,Evaluate left, then right; produce right operand’s value(x = 6, x + 2) → 8
Subscript [] / call ()Array element access / function calla[0], printf(...)
Member . / ->Structure member / member through a structure pointerstudent.roll, p->roll (later topics)

A comma between function arguments or declarations is a separator, not the comma operator. Parentheses around (x = 6, x + 2) group a comma expression. Pointer, array and structure operations will be developed in later units.

Address, indirection, comma, sizeof and castmain.c
#include <stdio.h>
int main(void)
{
    int x = 4, y;
    int *p = &x;
    y = (x = 6, x + 2);
    printf("x = %d, y = %d, *p = %d\n", x, y, *p);
    printf("Object has storage: %d\n", sizeof x > 0);
    printf("Floating division = %.1f\n", (double)5 / 2);
    return 0;
}
EXPECTED OUTPUTx = 6, y = 8, *p = 6 Object has storage: 1 Floating division = 2.5

Try this program

UNIT 02 · 07

Group correctly before you calculate.

Precedence decides how different operators group. Associativity decides grouping when operators share a precedence level. Parentheses explicitly group a subexpression. The table lists C90 operators from higher to lower precedence; context distinguishes unary * from multiplication and unary & from bitwise AND.

LevelOperatorsAssociativity
1 · highest() [] . -> postfix ++ --Left to right
2prefix ++ -- + − ! ~ (type) * & sizeofRight to left
3* / %Left to right
4+ −Left to right
5<< >>Left to right
6< <= > >=Left to right
7== !=Left to right
8&Left to right
9^Left to right
10|Left to right
11&&Left to right
12||Left to right
13?:Right to left
14= += -= *= /= %= <<= >>= &= ^= |=Right to left
15 · lowest,Left to right

2 + 3 * 4 groups as 2 + (3 * 4). 10 - 3 - 2 groups as (10 - 3) - 2. a = b = 7 groups as a = (b = 7), setting both to seven.

Grouping is not execution order

Precedence does not specify which operand is evaluated first. C does not generally guarantee left-to-right evaluation of function arguments or arithmetic operands. Logical AND/OR, the conditional operator and the comma operator provide specific sequencing rules. Use separate statements for side effects.

EXPLORE THE CONCEPT

Walk through an expression

    These are guided examples of C expression rules. Use the C playground to compile your own expressions.

    UNIT 02 · 08

    Choose the next path.

    An if executes its body when an expression compares unequal to zero. An if-else selects one of two bodies. An else if ladder tests conditions in order and takes the first true branch. Nest an if inside another branch when a second decision depends on the first.

    if (condition) {
        /* true branch */
    } else {
        /* false branch */
    }
    
    if (marks >= 80) grade = 'A';
    else if (marks >= 60) grade = 'B';
    else if (marks >= 40) grade = 'C';
    else grade = 'F';

    Without braces, an else belongs to the nearest unmatched if. Braces make the intended nesting explicit. A semicolon immediately after if (condition); makes its body an empty statement, a common logic error.

    EXPLORE THE CONCEPT

    Follow the grade ladder

    1. marks ≥ 80 → A
    2. otherwise, marks ≥ 60 → B
    3. otherwise, marks ≥ 40 → C
    4. otherwise → F

    These grade thresholds are illustrative, not an official university grading scheme.

    if / else-if / else: grade laddermain.c
    #include <stdio.h>
    int main(void)
    {
        int marks;
        char grade;
        if (scanf("%d", &marks) != 1 || marks < 0 || marks > 100) {
            puts("Enter marks from 0 to 100.");
            return 1;
        }
        /* Illustrative thresholds, not a university grading policy. */
        if (marks >= 80) grade = 'A';
        else if (marks >= 60) grade = 'B';
        else if (marks >= 40) grade = 'C';
        else grade = 'F';
        printf("Grade = %c\n", grade);
        return 0;
    }
    
    EXPECTED OUTPUTGrade = B

    Try this program

    UNIT 02 · 09

    Select a case. Leave or skip a step.

    switch evaluates an integer expression and transfers control to a matching case label. Labels use unique integer constant expressions, such as case 1: or case 'A':. A default label handles unmatched values and is optional.

    A switch does not automatically stop at the next label. Execution falls through unless a jump such as break or return exits. Cases cannot directly match string values or floating-point values. For ranges, use an if-else ladder.

    switch: choose a menu optionmain.c
    #include <stdio.h>
    int main(void)
    {
        int choice;
        if (scanf("%d", &choice) != 1) {
            puts("Enter an integer menu choice.");
            return 1;
        }
        switch (choice) {
            case 1: puts("Open the notes"); break;
            case 2: puts("Open the lab"); break;
            case 3: puts("Open the revision questions"); break;
            default: puts("Unknown choice"); break;
        }
        return 0;
    }
    
    EXPECTED OUTPUTOpen the lab

    Try this program
    StatementEffectTypical use
    break;Exits the innermost enclosing loop or switchStop a search or end a case
    continue;Skips the rest of the current loop iterationIgnore an unwanted item; in for, the update expression still runs
    goto label;Jumps to a named label within the same functionA forward error exit in a small example; structured loops are clearer for repetition

    In a while or do-while loop, continue moves to the condition check; ensure the loop’s state still advances. A break inside a switch nested in a loop leaves the switch, not the surrounding loop. A label has the syntax label: and, in C90, must precede a statement.

    break and continue in a for loopmain.c
    #include <stdio.h>
    int main(void)
    {
        int i, sum = 0;
        printf("Accepted:");
        for (i = 1; i <= 7; i++) {
            if (i == 3) continue;
            if (i > 5) break;
            printf(" %d", i);
            sum += i;
        }
        printf("\nSum = %d\n", sum);
        return 0;
    }
    
    EXPECTED OUTPUTAccepted: 1 2 4 5 Sum = 12

    Try this program
    goto: one forward error pathmain.c
    #include <stdio.h>
    int main(void)
    {
        int value;
        if (scanf("%d", &value) != 1) goto invalid;
        if (value <= 0) goto invalid;
        printf("Accepted positive value: %d\n", value);
        return 0;
    invalid:
        puts("A positive integer is required.");
        return 1;
    }
    
    EXPECTED OUTPUTAccepted positive value: 4

    Try this program

    UNIT 02 · 10

    Repeat with a clear stopping condition.

    LoopSyntaxWhen the condition is tested
    whilewhile (condition) { body; }Before each iteration; the body can run zero times
    do-whiledo { body; } while (condition);After each iteration; the body runs at least once
    forfor (initialization; condition; update) { body; }Initialization once, then condition → body → update → condition

    Choose a while when repetition depends on a changing condition, a do-while when one attempt must occur, and a for when initialization, test and update fit naturally together. These are conventions, not restrictions. A for can omit its condition to make it always true; every loop still needs a reachable way to finish when the task requires one.

    EXPLORE THE CONCEPT

    Trace the same sum with three loops

      This trace follows the unguarded loops in the example. Try N = 0: while and for sum to 0; do-while executes once and sums to 1. To implement a mathematical sum for N = 0 with do-while, guard the loop with if (n > 0).

      while, do-while and for: comparemain.c
      #include <stdio.h>
      int main(void)
      {
          int n, i, sum;
          if (scanf("%d", &n) != 1 || n < 0 || n > 10) {
              puts("Enter n from 0 to 10.");
              return 1;
          }
          i = 1; sum = 0;
          while (i <= n) { sum += i; i++; }
          printf("while sum = %d\n", sum);
          i = 1; sum = 0;
          do { sum += i; i++; } while (i <= n);
          printf("do-while sum = %d\n", sum);
          sum = 0;
          for (i = 1; i <= n; i++) { sum += i; }
          printf("for sum = %d\n", sum);
          return 0;
      }
      
      EXPECTED OUTPUTwhile sum = 6 do-while sum = 6 for sum = 6

      Try this program

      Nested loops

      A nested loop places one loop inside another. For each outer iteration, the inner loop starts again when its initialization is reached. A rectangular grid with R rows and C columns visits R × C positions; a triangle with N rows prints 1 + 2 + … + N stars. In the triangle program, row is the outer counter and column is the inner counter.

      EXPLORE THE CONCEPT

      Build a triangle, one star at a time

      Ready to print.

      row = 1, column = 1

      Nested for loops: star trianglemain.c
      #include <stdio.h>
      int main(void)
      {
          int rows, row, column;
          if (scanf("%d", &rows) != 1 || rows < 1 || rows > 6) {
              puts("Enter rows from 1 to 6.");
              return 1;
          }
          for (row = 1; row <= rows; row++) {
              for (column = 1; column <= row; column++) {
                  putchar('*');
              }
              putchar('\n');
          }
          return 0;
      }
      
      EXPECTED OUTPUT* ** ***

      Try this program

      A quick loop checklist

      • Initialize every counter and accumulator before reading it.
      • Check boundary values: zero iterations, one iteration, and the last iteration.
      • Update the state on every repeating path, including paths using continue.
      • Use < versus <= deliberately; dry-run the final counter value.
      • Do not place an unintended semicolon after a loop header.

      UNIT 02 · 11

      Edit it. Run it. Explain it.

      Choose an example and load it into the embedded C compiler. Select I/O inside the compiler, check the sample STDIN, and press Run. Change the input or edit the source to explore a different case.

      Sample input (STDIN)

      7 85.5

      Expected output

      Roll: 007
      Marks: 85.50
      Completion: 100%
      

      Load the compiler when you’re ready to practise.

      Your C workspace

      Edit real C code and see real compiler output.

      Compiler provided by OneCompiler. Opening the editor connects to that service; code and input you run are processed there. If the embed is unavailable, open the C compiler in a new tab and paste the source below.

      View / copy the selected source
      #include <stdio.h>
      int main(void)
      {
          int roll;
          double marks;
          if (scanf("%d %lf", &roll, &marks) != 2) {
              puts("Enter a roll number and marks.");
              return 1;
          }
          printf("Roll: %03d\n", roll);
          printf("Marks: %.2f\n", marks);
          printf("Completion: 100%%\n");
          return 0;
      }
      

      Experiments to try

      • Arithmetic: compare inputs 7 2 and 8 2. Explain the integer quotient and remainder.
      • Logical: use 8 0. Why does the guarded division remain safe?
      • Grade: test 39, 40, 59, 60, 79 and 80. Explain each boundary.
      • Switch: try choice 9, then remove one break and inspect fall-through.
      • Loops: use N = 0 and N = 1. Add a guard to the do-while version and compare.
      • Nested loops: change the inner condition from column <= row to column <= rows to print a square.

      UNIT 02 · 12

      Finish with a self-check.

      1. What does printf("%.2f", 3.5) display?
      2. Which scanf conversion reads into a double object?
      3. Why is fgets preferred to gets?
      4. What is 7 / 2 when both operands are int?
      5. Starting with x = 5, after value = x++, what are value and x?
      6. Which expression safely guards division when b might be zero?
      7. What is 2 + 3 * 4?
      8. What does break exit?
      9. Which loop always executes its body at least once when reached normally?
      10. In a for loop, what happens after continue?

      Written exam practice

      1. Explain printf and scanf with control strings, field width, precision and suitable examples.
      2. Describe escape sequences and distinguish formatted and unformatted I/O.
      3. Explain getchar, putchar, gets and puts; show a bounded replacement for gets.
      4. Classify C operators and explain integer division, logical short-circuiting and bitwise operations.
      5. Distinguish prefix and postfix increment with a dry run of separate statements.
      6. Explain precedence and associativity; evaluate a parenthesized arithmetic expression.
      7. Write an if-else ladder and a switch program; explain fall-through and break.
      8. Compare goto, break and continue with their scope and effects.
      9. Compare while, do-while and for using N = 0 and N = 3 as test cases.
      10. Write a nested-loop triangle program and trace row and column values.
      Build a complete answer

      Give the definition, syntax and a small example. State the types and input assumptions. Show the result or dry run, and explain a boundary case. For loops, include initialization, condition, update and the stopping state. For library input, include the destination capacity and return-value check.

      UNIT 02 · 13

      Read alongside your textbook.

      E. Balagurusamy, Programming in ANSI C, Eighth Edition, McGraw Hill Education (India) Private Limited. ISBN 9789353165130.

      Use your copy for the chapters on operators and expressions, input/output, decision making and looping. These original notes and programs follow the supplied Unit 2 syllabus; they do not reproduce the book’s chapter text or claim page-by-page correspondence. Runnable examples use portable C90 syntax, with later-standard differences identified where relevant.