Unit 2: Principles of programming

CAP1008 — C Programming 7 min read

C (developed by Dennis Ritchie at Bell Labs, 1972) is a structured, compiled, procedural language. A C program is translated by a compiler into machine code, and every program obeys a fixed grammar built from a small character set, a set of reserved words, and rules for naming and typing data. This unit establishes those building blocks.

  • Structured and procedural: logic is organised into functions; main() is the mandatory entry point.
  • Compiled: source (.c) is preprocessed, compiled, and linked into an executable.
  • Case-sensitive: Sum, sum, and SUM are three distinct identifiers.
  • Statement terminator: every executable statement ends with a semicolon ;.
  • Free-format: whitespace and line breaks are ignored by the compiler but used for readability.

II. Program Structure and Building Blocks

The skeleton of every C source file and the tokens it is made from.

A. C program structure

A C program is a collection of sections arranged in a conventional order.

  • Documentation section: comments, written /* ... */ or // ..., ignored by the compiler.
  • Preprocessor / link section: directives like #include <stdio.h> pull in library declarations before compilation.
  • Definition section: symbolic constants via #define PI 3.14.
  • Global declaration: variables and function prototypes visible to all functions.
  • main() function: execution always begins here; contains declarations and statements inside { }.
  • Subprogram section: user-defined functions called from main().
C
#include <stdio.h>          /* link section */
#define PI 3.14159          /* definition */
int main(void) {            /* main function */
    printf("Area basis: %f", PI);
    return 0;               /* status to OS */
}

B. Character set

The character set is the collection of symbols the compiler recognises.

  • Letters: uppercase A–Z and lowercase a–z.
  • Digits: 0–9.
  • Special characters: symbols such as + - * / % = < > ( ) { } [ ] ; , . # & | ^ ~ !.
  • White space: blank, tab (\t), newline (\n), carriage return.
  • Escape sequences: backslash combinations like \n (newline), \t (tab), \0 (null), \\ (backslash).

C. Identifiers and keywords

These are the two token categories used to name things and to signal grammar.

  1. Identifiers: programmer-chosen names for variables, functions, arrays.
    • Rules: begin with a letter or underscore, followed by letters, digits, or _; no spaces or special symbols; keywords cannot be reused. roll_no, _count, total2 are valid; 2total, net-pay are not.
  2. Keywords: 32 reserved words with fixed meaning in standard C.
    • Examples: int, float, char, if, else, while, for, return, void, struct, const, static. They are always lowercase and cannot serve as identifiers.

III. Constants, Variables and Data Types

How C stores and labels values in memory.

A. Constants and variables

A constant is a value that cannot change during execution; a variable is a named memory location whose value can change.

  • Integer constants: whole numbers, e.g. 75, -12, 0xFF (hex), 075 (octal).
  • Real/floating constants: 3.14, 1.5e3 (= 1500.0) in exponential form.
  • Character constant: a single symbol in single quotes, 'A', stored as its ASCII code (65).
  • String constant: characters in double quotes, "Hello", terminated by \0.
  • Symbolic constant: #define MAX 100 or const int max = 100;.
  • Variable: declared as type name;, e.g. int age;; may be initialised int age = 20;.

B. Data types

Data types fix the size and interpretation of stored values.

  • Primary (built-in):
    • char — 1 byte, single character/small integer, format %c.
    • int — typically 2 or 4 bytes, whole numbers, format %d.
    • float — 4 bytes, single-precision real, format %f.
    • double — 8 bytes, double-precision real, format %lf.
    • void — no value; used for functions returning nothing.
  • Derived types: arrays, pointers, functions.
  • User-defined types: struct, union, enum, typedef.
  • sizeof operator: returns the byte size of a type, e.g. sizeof(int).

IV. Input and Output Functions

Console I/O supplied by <stdio.h>, split into formatted and unformatted.

A. Formatted I/O

Formatted functions convert data using format specifiers (%d, %f, %c, %s).

  1. printf(): sends formatted output to the screen.
    • Syntax: printf("format string", arg1, arg2, ...);
    • Example: printf("Total = %d\n", 50); prints Total = 50.
  2. scanf(): reads formatted input from the keyboard into variables via their addresses.
    • Syntax: scanf("%d", &n); — the & supplies the address of n.
    • Example: scanf("%d %f", &qty, &rate); reads an int and a float.

B. Unformatted I/O

Unformatted functions handle characters and strings without conversion specifiers.

  • getchar(): reads one character from input; returns it as an int. ch = getchar();
  • putchar(): writes one character to output. putchar(ch);
  • gets(): reads a whole line (including spaces) into a string until newline. gets(name);
  • puts(): writes a string followed by a newline. puts(name);
C
char name[20];
gets(name);           /* reads "John Doe" with the space */
puts(name);           /* prints it and moves to next line */

V. Expressions and Operators

How operands and operators combine to produce values.

A. Expressions

An expression is a combination of operands (constants, variables) and operators that yields a single value.

  • Evaluation: governed by operator precedence and associativity, e.g. a + b * c multiplies first.
  • Parentheses: override default order; (a + b) * c adds first.
  • Example: x = 3 + 4 * 2; assigns 11, not 14.

B. Arithmetic operators

These perform mathematical calculations on numeric operands.

  • Operators: +, -, *, /, % (modulus, remainder).
  • Integer division: 7 / 2 gives 3 (fraction discarded); 7 % 2 gives 1.
  • Real division: 7.0 / 2 gives 3.5.
  • Note: % works only on integers, never on float.

C. Unary operator

A unary operator acts on a single operand.

  • Increment/decrement: ++ and -- add or subtract 1.
    • Prefix: ++a changes then uses the value.
    • Postfix: a++ uses then changes the value; if a=5, b=a++ leaves b=5, a=6.
  • Unary minus: -x negates.
  • Others: ! (logical NOT), sizeof, address-of &.

D. Relational operator

These compare two values and return 1 (true) or 0 (false).

  • Operators: <, >, <=, >=, == (equal to), != (not equal to).
  • Use: control conditions, e.g. if (marks >= 40).
  • Caution: == tests equality; = assigns — a common bug.

E. Logical operator

These combine or invert relational expressions.

  • && (AND): true only if both operands are true — (a>0 && b>0).
  • || (OR): true if at least one is true — (a==0 || b==0).
  • ! (NOT): reverses truth — !(a>b).
  • Short-circuit: with &&, if the left side is false the right is not evaluated.

F. Assignment and conditional operator

These paired operators store values and choose between them.

  1. Assignment operator =: stores the right value into the left variable.
    • Compound forms: +=, -=, *=, /=, %=; a += 5 means a = a + 5.
  2. Conditional (ternary) operator ?:: a three-operand shorthand for if-else.
    • Syntax: result = (condition) ? value_if_true : value_if_false;
    • Example: big = (a > b) ? a : b; assigns the larger of a and b.

G. Bitwise operators

These operate on the individual bits of integer operands.

  • & (AND): bit is 1 only if both bits are 1.
  • | (OR): bit is 1 if either bit is 1.
  • ^ (XOR): bit is 1 if bits differ.
  • ~ (complement): inverts every bit.
  • << / >> (shift): move bits left/right; x << 1 doubles, x >> 1 halves.
  • Example: 5 & 3 → 0101 & 0011 = 0001 = 1.

VI. Type Conversion and Type Modifiers

Adjusting how values are interpreted and how much range a type holds.

A. Type conversion

Type conversion changes a value from one data type to another.

  1. Implicit conversion (type promotion): the compiler converts automatically in mixed expressions, promoting lower to higher (int → float → double).
    • Example: 3 + 2.5 promotes 3 to 3.0, giving 5.5.
  2. Explicit conversion (type casting): the programmer forces a type with (type).
    • Syntax: (float) x or avg = (float) sum / n; to keep the decimal part.

B. Type modifiers

Modifiers alter the size or sign of the basic data types.

  • signed / unsigned: decide whether negatives are allowed; unsigned int doubles the positive range by dropping the sign bit.
  • short / long: shrink or extend storage; long int, short int, long double.
  • Combined use: unsigned long int holds large non-negative numbers.
  • Effect: modifiers change the range of representable values, not the base kind of data — unsigned char still stores a character-sized 1-byte value but ranges 0–255 instead of −128 to 127.