All notes

Programming in C

GATE CS60 min read

Free preview: 30% of the note

C program structure and execution

Definition. A C program consists of declarations and function definitions; execution begins at main. A compiler translates source into an executable, while the runtime environment provides startup and library support. A statement generally ends with a semicolon, and braces delimit compound statements and scopes.

Example. int main(void) { return 0; } defines a program entry function.

Exam point. Distinguish syntax errors, run-time errors, and implementation-defined or undefined behavior.

Basic types and object representation

Definition. C has integer, floating, character, and derived types such as arrays, pointers, structures, and unions. Exact widths of many integer types are implementation-dependent, though minimum ranges are specified by the language standard. An object occupies storage and has a type that determines valid operations and interpretation.

Type familyExamplesTypical use
Integerchar, short, int, longCounts and discrete values
Floatingfloat, doubleApproximate real values
Derivedarray, pointer, structureAggregate and indirect data

Example. int count = 7; declares an integer object initialized to 7.

Exam point. Do not assume int is exactly 32 bits unless the question states it.

Integer arithmetic and conversion

Definition. Integer division discards the fractional part toward zero when operands have integer type. Usual arithmetic conversions may convert operands before an operation. Signed overflow is undefined behavior in standard C; unsigned arithmetic wraps modulo one more than the maximum representable value.

Example. 7 / 2 evaluates to 3 when both operands are integers.

Exam point. Determine operand types before predicting an expression's value.

Solved trace. Find the values printed by this code on a system where int is representable for the shown results.

int a = 7, b = 2;
printf("%d %.1f", a / b, (double)a / b);
  1. a / b uses integer division, so it is 3.
  2. (double)a converts a to floating type before division.
  3. Floating division gives 3.5.
  4. The format prints the integer then one decimal digit. Answer. 3 3.5.

Operators, precedence, and associativity

Definition. Operators have precedence and associativity rules that determine grouping when parentheses are absent. Precedence does not specify evaluation order for all operands. In particular, side effects on the same scalar object without sequencing can make an expression undefined; add parentheses for grouping but do not rely on them to order side effects.

Example. a + b * c groups as a + (b * c).

Exam point. Never assume left-to-right evaluation unless the language rule guarantees it.

Solved trace. Evaluate x + 2 * y when x=3 and y=4.

  1. Multiplication has higher precedence than addition.
  2. Compute 2×4=82\times4=8.
  3. Add x: 3+8=113+8=11. Answer. 11.

Increment and decrement operators

Definition. Prefix increment changes the object and yields its new value; postfix increment yields the old value and then changes the object. The modification occurs as a side effect. Multiple unsequenced modifications or conflicting accesses to one scalar in an expression may produce undefined behavior.

Example. With i=5, j=++i sets both to 6; j=i++ sets j to 5 and then i to 6.

Exam point. Trace the value yielded separately from the object's final value.

Solved trace.

int i = 3;
int a = i++;
int b = ++i;
  1. Initially i=3.
  2. i++ yields 3 to a, then i becomes 4.
  3. ++i first changes i to 5 and yields 5 to b. Answer. a=3, b=5, i=5.

Conditional and logical operators

Definition. The conditional operator ?: evaluates its condition and then exactly one of its second and third operands. Logical && and || short-circuit: the right operand is evaluated only when needed to determine the result. Bitwise & and | evaluate both operands and operate on their bits.

Example. p != NULL && *p > 0 does not dereference p when p is null.

Exam point. Short-circuiting can prevent a dangerous or unnecessary evaluation.

Solved trace.

int x = 0;
int y = (x != 0 && 10 / x > 1);
  1. x != 0 is false.
  2. && short-circuits, so 10/x is not evaluated.
  3. The whole logical expression is false, represented by 0. Answer. y=0; no division by zero occurs.

Scope and name visibility

Definition. Scope is the region of source code where an identifier can be used. A block-scope declaration is visible from its declaration to the end of the block; a file-scope declaration is visible from its declaration through the translation unit, subject to linkage rules. An inner declaration can hide an outer identifier with the same name.

Example. A local int x inside a function hides a file-scope x while that local is in scope.

Exam point. Scope controls name lookup; it is distinct from object lifetime.

Solved trace.

int x = 4;
int main(void) {
    int x = 7;
    { int x = 9; printf("%d ", x); }
    printf("%d", x);
}
  1. In the nested block, the innermost x is 9.
  2. At the second printf, the nested block has ended and the function-local x is 7.
  3. The file-scope x remains hidden in the function. Answer. Output is 9 7.

Storage duration and lifetime

Definition. Storage duration describes how long an object's storage exists. Automatic objects in blocks usually exist during that block execution; static-duration objects exist for the entire program; allocated objects exist from successful allocation until deallocation. A pointer's lifetime is separate from the lifetime of the object it points to.

Example. A local automatic variable ceases to exist when its block exits.

Exam point. Returning the address of a non-static local object leaves a dangling pointer.

Static local variables

Definition. A local object declared static has block scope but static storage duration. It is initialized once before program execution (or zero-initialized when no explicit initializer is given) and retains its value between function calls. Its name remains visible only within its block.

Example. A static call counter increases across repeated calls.

Exam point. Do not confuse a static local's visibility with its lifetime.

Solved trace.

int f(void) { static int n = 0; return ++n; }
int main(void) {
    int a = f();
    int b = f();
    int c = f();
    printf("%d %d %d", a, b, c);
}
  1. Each call increments the same static n.
  2. Separate statements fix the call order; the functions return 1, then 2, then 3.
  3. The final printf reads those saved values. Answer. Output is 1 2 3.

Function parameters and pass-by-value

Definition. C passes each argument value to its corresponding parameter. A parameter is a local object initialized from the argument; assigning to it does not assign to the caller's object. To modify a caller object, pass a pointer to it and update through that pointer.

Example. void set(int *p) { *p = 8; } can change an integer passed by address.

Exam point. C does not have built-in pass-by-reference parameters.

Solved trace.

void f(int x) { x = x + 5; }
int main(void) { int a = 2; f(a); printf("%d", a); }
  1. The value 2 is copied into parameter x.
  2. The function changes its local x to 7.
  3. The caller's a is a separate object and remains 2. Answer. Output is 2.

Pointers and address operators

Definition. A pointer object stores an address of an object or function of a compatible type, or a null pointer. Unary & obtains an object's address; unary * accesses the pointed-to object when the pointer is valid and points to a live object. Dereferencing null, indeterminate, or dangling pointers is undefined behavior.

You have read the free 30% of this note

Sign in with Google to keep reading. It is free, takes one tap, and you also get:

  • 6 practice questions from this note
  • Every note in full, plus the PDF library
  • Official past papers as timed tests, with explanations
  • An AI tutor for doubts, in Hindi or English
  • Your progress, mistakes and study plan saved on every device
Continue reading, free