Karnataka KSEAB SSLC JTS Programming in ANSI C cheat sheet
Karnataka KSEAB SSLC JTS Programming in ANSI C · Keep the key ideas within reach.
C Fundamentals: Character Set, Tokens, Identifiers, Keywords, Data Types, Constants, Variables, Declarations
C source uses the ASCII character set: letters, digits, underscore, whitespace, and punctuation/special symbols such as + - * / % & | ^ ~ ! < > = ( ) [ ] { } , ; : ? . " ' # \ .
Six token classes: keywords, identifiers, constants, string literals, operators, and separators (punctuation). Whitespace separates tokens but is not itself a token.
Identifiers: first character must be a letter or underscore, remaining characters letters, digits, or underscore; case-sensitive; keywords are reserved and cannot be used; C99 guarantees 31 significant characters for internal names.
C89 keywords include auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while; C99 adds inline restrict _Bool _Complex _Imaginary.
Basic type sizes on typical 32/64-bit implementations: char 1 byte, short 2, int 4, long 4 or 8, long long 8, float 4, double 8, long double 10-16; sizeof yields size_t and is the portable way to check.
Integer constants: decimal (no leading 0), octal (leading 0), hexadecimal (0x or 0X); suffixes u/U and l/L or ll/LL set type. Floating constants default to double; suffix f/F makes float, l/L makes long double.
Character constants use single quotes ('A', '\n', '\0'); a string literal uses double quotes and is stored as a char array terminated by the null character '\0'.
Declarations give type and name (int count;); definitions allocate storage. A declaration with extern refers to storage defined elsewhere; initializers may appear at definition.
const makes an object read-only after initialization; #define creates a textual constant with no type. Enum constants are integer constants and are an alternative to #define for related values.
Storage-class specifiers (auto, register, static, extern, typedef) combine with type specifiers in a declaration; default for local variables is auto.
Operators and Expressions: Arithmetic, Relational, Logical, Bitwise, Assignment, Increment/Decrement, Precedence, Type Conversion
Precedence high to low: postfix () [] -> . ++ --; unary ! ~ + - ++ -- * & sizeof (type); multiplicative * / %; additive + -; shift << >>; relational < <= > >=; equality == !=; bitwise & then ^ then |; logical && then ||; conditional ?:; assignment = += -= etc.; comma.
Associativity: most binary operators are left-to-right; assignment, conditional ?:, and unary operators are right-to-left.
Integer division truncates toward zero; the % operator requires integer operands and the sign of the result follows the dividend (e.g., -7 % 3 gives -1).
Relational and logical expressions yield int 1 for true and 0 for false. && and || short-circuit: the right operand is not evaluated when the result is already determined.
Bitwise operators: & AND, | OR, ^ XOR, ~ complement, << left shift (multiplies by 2^n for non-negative values), >> right shift. Use unsigned types for shifts to avoid implementation-defined sign behavior.
Increment/decrement: ++i increments then yields the new value; i++ yields the old value then increments. Modifying a variable twice between sequence points (e.g., i = i++ + 1) is undefined behavior.
Assignment operators are right-associative: a = b = c assigns c to b, then b to a; compound forms a += b are equivalent to a = a + b.
Usual arithmetic conversions: char and short promote to int; if either operand is double, the other converts to double; if either is float, to float; otherwise integer promotion then higher rank wins (unsigned long > long > unsigned int > int).
Explicit conversion uses a cast: (float) a / b forces floating division. Implicit narrowing (e.g., int to char) may truncate and is a common source of bugs.
The conditional operator a ? b : c evaluates a first; only one of b or c is evaluated, and the result type is the common type of b and c.
sizeof returns size_t (unsigned); comparing sizeof with a negative int can produce surprising results because of the usual conversions.
Control Structures: if, if-else, switch, for, while, do-while, break, continue, goto
if (expr) statement; else statement; - the expression is true when nonzero; an else binds to the nearest unmatched if.
switch (integer_expr) { case const1: ... break; default: ... } - the controlling expression must be an integer or enum type; case labels must be integer constant expressions and unique within the switch.
Without break, control falls through to the next case; this is intentional in some designs (e.g., grouping cases) but is a frequent bug source.
for (init; condition; update) body - init runs once; condition is tested before each iteration; update runs after each iteration; any clause may be empty (for(;;) is an infinite loop).
while (condition) body - tests before each iteration; the body may execute zero times.
do body while (condition); - executes the body at least once, then tests; note the required semicolon after the while condition.
break exits the innermost enclosing loop or switch immediately; continue skips the rest of the current iteration and proceeds to the next test/update.
goto label; jumps within the same function to a labeled statement; it cannot jump into another function. It is sometimes used to break out of nested loops or to a single cleanup label.
A common loop pattern for reading input: while (scanf("%d", &x) == 1) { ... } stops when scanf fails or reaches EOF.
Functions: Declaration, Definition, Call, Parameters, Return Values, Recursion, Scope, Storage Classes
A function declaration (prototype) gives the return type, name, and parameter types, e.g., int add(int a, int b); it lets the compiler check calls before the definition appears.
A definition provides the body; a program may have many declarations but only one definition of a non-static function.
Parameters are passed by value: the function receives copies. To modify a caller's variable, pass its address (pointer) and dereference inside the function.
return expr; sends a value back; a function with return type void returns no value. Falling off the end of a non-void function without returning is undefined behavior if the value is used.
Recursion: a function calls itself with a smaller problem and a base case that stops the recursion. Each call consumes stack space; deep recursion can overflow the stack.
Scope: block scope for variables declared inside { }, function scope for labels, file scope for declarations outside functions. A local variable hides a same-named global.
Storage classes: auto (default local, automatic lifetime), register (hint for fast access, address cannot be taken), static (local: retains value between calls; file-scope: internal linkage), extern (declaration referring to external linkage).
Static local variables are initialized once, before the first call, and retain their value across calls; they are not reinitialized on each entry.
Arguments are evaluated in unspecified order; a function call's arguments should not depend on the order of evaluation of other arguments.
Arrays and Strings: One- and Two-Dimensional Arrays, String Handling, Standard String Functions
An array of n elements is indexed 0 to n-1; accessing outside that range is undefined behavior and is not checked by the compiler.
Declaration int a[10]; allocates 10 ints; initialization int a[5] = {1, 2}; sets the rest to 0. The array size may be omitted when an initializer is present: int a[] = {1,2,3};
A two-dimensional array int m[3][4]; is an array of 3 arrays of 4 ints; elements are stored in row-major order. m[i] is a pointer to the i-th row.
An array name in an expression decays to a pointer to its first element, except with sizeof and the address-of operator.
A C string is a char array ending with '\0'; the length excludes the terminator, so "hello" needs 6 bytes.
String functions from <string.h>: strlen (length), strcpy/strncpy (copy), strcat/strncat (concatenate), strcmp/strncmp (compare, returns <0, 0, or >0), strchr/strstr (search), memset, memcpy.
strcpy and strcat do not check the destination size; use strncpy/strncat or size-aware code to avoid buffer overflows.
String literals are read-only; modifying one (e.g., strcpy("abc", ...)) is undefined behavior. Copy into a char array first.
Reading a string: scanf("%s", buf) stops at whitespace and can overflow; fgets(buf, size, stdin) reads a line and is safer.
sizeof(array) gives the total byte size; to get element count use sizeof(a)/sizeof(a[0]) only where the array type is visible (not after decay to a pointer).
Pointers: Declaration, Pointer Arithmetic, Pointers and Arrays, Pointers and Functions, Dynamic Memory
int *p; declares a pointer to int. & takes an address; * dereferences. A pointer must point to a valid object before it is dereferenced.
Pointer arithmetic is in units of the pointed-to type: if p is int* and int is 4 bytes, p+1 advances 4 bytes. Adding two pointers is illegal; subtracting two pointers in the same array yields an element count.
For an array a, a[i] is defined as *(a + i); the compiler treats a and &a[0] identically in expressions (except sizeof and &).
Passing a pointer to a function lets the function modify the caller's data: void swap(int *a, int *b) { int t = *a; *a = *b; *b = t; } called as swap(&x, &y);
A pointer to a function is declared with the return type and parameter list, e.g., int (*fp)(int, int); it can be called as fp(2,3) or (*fp)(2,3).
Dynamic memory: malloc(size) allocates uninitialized bytes, calloc(n, size) allocates zeroed elements, realloc(ptr, size) resizes, free(ptr) releases. Each successful allocation must be freed exactly once.
malloc returns NULL on failure - always check before use; after free, set the pointer to NULL to avoid a dangling reference.
Common pointer errors: dereferencing NULL or an uninitialized pointer, using memory after free, double free, and leaking memory by losing the only pointer.
Structures, Unions, Enumerations, typedef
struct Point { int x; int y; }; defines a type; a variable is declared as struct Point p; and members are accessed with p.x and p.y.
A pointer to a struct uses the arrow operator: struct Point *q = &p; then q->x is equivalent to (*q).x.
Structs may be initialized with a brace list in member order: struct Point p = {1, 2}; members are stored in declaration order, possibly with padding for alignment.
Structs are passed by value (copied); pass a pointer (often const struct T *) to avoid copying large structs.
A union stores all members in the same memory; its size is at least the size of the largest member. Only one member is valid at a time.
enum Color { RED, GREEN, BLUE }; defines integer constants starting at 0 and increasing by 1; explicit values may be assigned (e.g., RED = 1).
typedef creates an alias: typedef unsigned long ulong; typedef struct Node Node; lets you write Node n; instead of struct Node n;.
A self-referential struct (linked list node) needs a pointer member: struct Node { int data; struct Node *next; };.
Bit-fields let a struct member occupy a specified number of bits: struct Flags { unsigned a : 1; unsigned b : 2; }; layout is implementation-dependent.
Input/Output and File Handling: printf/scanf, Character and Formatted I/O, File Open/Close/Read/Write
printf format specifiers: %d int, %u unsigned, %ld long, %f double (fixed), %e scientific, %g shortest, %c char, %s string, %p pointer, %x/%o hex/octal, %% literal percent.
scanf needs addresses for most conversions: scanf("%d", &x); but %s takes a char array name (already an address). It returns the number of items successfully assigned, or EOF.
Common scanf pitfall: a space in the format matches any amount of whitespace; a newline left in the input buffer can cause the next %c to read '\n'.
Character I/O: getchar/putchar for one character; fgetc/fputc for files; EOF is returned at end of input and is a negative int, so store getchar results in int, not char.
File handling: FILE *fp = fopen("data.txt", "r"); modes include r, w, a, r+, w+, a+, and b for binary. Always check for NULL. Close with fclose(fp).
Reading and writing files: fprintf/fscanf for formatted text, fgets/fputs for lines, fread/fwrite for binary blocks. fgetc returns EOF at end of file; feof(fp) tests the end-of-file indicator after a read attempt.
fflush(fp) forces buffered output to be written; fseek(fp, offset, SEEK_SET/SEEK_CUR/SEEK_END) and ftell(fp) support random access.
stdin, stdout, and stderr are predefined FILE * streams; perror("msg") prints a message plus the system error text to stderr.
Preprocessor Directives and Standard Library Overview
Preprocessor directives start with # at the beginning of a line: #include, #define, #undef, #if, #ifdef, #ifndef, #else, #elif, #endif, #line, #error, #pragma.
#include <stdio.h> searches system directories; #include "myfile.h" searches the current directory first, then system directories.
Object-like macro: #define PI 3.14159. Function-like macro: #define SQUARE(x) ((x)*(x)) - parenthesize parameters and the whole body to avoid precedence bugs.
Macros are textual substitution performed before compilation; they have no type checking and no scope. Use inline functions or const variables where possible.
Include guards prevent multiple inclusion: #ifndef HEADER_H / #define HEADER_H / ... / #endif.
Conditional compilation with #ifdef DEBUG, #if defined(X), and #ifndef lets code be included or excluded per build.
The # operator in a macro stringizes an argument; ## concatenates tokens. FILE, LINE, DATE, and TIME are predefined macros.
Standard headers: <stdio.h> I/O, <stdlib.h> malloc/free/exit/atoi/rand, <string.h> string functions, <math.h> math functions, <ctype.h> character classification (isdigit, isalpha, toupper), <stddef.h> size_t and NULL, <limits.h> and <float.h> numeric limits, <time.h> date/time.
Program Development: Algorithm, Flowchart, Debugging, Compilation, Simple C Programs
Program development order: understand the problem, design an algorithm, draw a flowchart, write code, compile, test and debug.
Algorithm properties: finite (terminates), definite (each step unambiguous), has zero or more inputs, one or more outputs, and is effective (each step is executable).
Flowchart symbols: oval for start/end, parallelogram for input/output, rectangle for process, diamond for decision, arrows for flow; a loop is drawn with a decision and a back edge.
Compilation stages: preprocessing (#include, #define expansion) → compilation to assembly → assembly to object code → linking with libraries to produce an executable.
Typical commands: gcc -o prog prog.c compiles and links; gcc -c prog.c produces prog.o; gcc -Wall -Wextra enables warnings that catch many bugs.
Debugging techniques: read the compiler error (line number and message), insert printf statements to trace values, use a debugger (gdb) with breakpoints and step, and check boundary cases.
Common runtime errors: missing & in scanf, off-by-one array index, division by zero, uninitialized variables, missing break in switch, and forgetting to free allocated memory.
A minimal C program: #include <stdio.h> int main(void) { printf("Hello\n"); return 0; } - main returns int, and 0 signals successful termination.
Testing should cover normal input, boundary values (0, 1, maximum), and invalid input; trace the algorithm by hand before coding to catch logic errors early.