C Program Structure and Data Types
C is a small, statically typed, compiled language in which the programmer works close to the machine: every object has a type that fixes how many bytes it occupies and how those bytes are interpreted.
PCC · Short notes
17 short notes in syllabus order, about 129 minutes to read end to end.
C is a small, statically typed, compiled language in which the programmer works close to the machine: every object has a type that fixes how many bytes it occupies and how those bytes are interpreted.
An expression in C computes a value and may also change the state of the program, for example by assigning to a variable or printing. The value depends on how the expression is grouped (precedence and associativity); the state changes depend on when each side effect happens (sequencing).
The bitwise operators work on the individual bits of integer values. They are how C programs pack flags into a word, extract fields from hardware registers and network headers, compute masks for hashing, and implement fast multiplication or division by powers of two.
C lets you mix types freely in an expression: char with int, int with unsigned, int with double. Before any arithmetic happens, the compiler silently converts the operands to a common type, following fixed rules. Most of the time the result is what you expect.
Before a C file is compiled, it passes through the preprocessor, which works on tokens rather than on C expressions or types.
Control-flow statements decide which statement runs next. C has selection statements (if, if-else, switch), iteration statements (while, do-while, for) and jump statements (break, continue, goto, return).
A function packages a computation behind a name and a list of parameters. Functions make programs readable, let code be reused, and are the mechanism behind recursion.
Every identifier in a C program raises three separate questions:
A function is recursive when it calls itself, directly or through other functions. Recursion expresses a problem in terms of smaller instances of the same problem: the factorial of n is n times the factorial of n-1; a binary tree is a root with two smaller binary trees.
For a short recursive C function there are four things to determine: what it prints, what it returns, how many times it is called (or how many times some line runs), or what a variable holds afterwards. Each has a reliable mechanical method.
A pointer is a value that holds the address of an object (or function), together with the type of what it points to.
In C a pointer can hold the address of a function as well as of an object.
Fixed-size automatic arrays have compile-time sizes, but a variable-length automatic array (VLA) can have a runtime size. Automatic objects have block-based lifetimes, not merely “until function return”; a VLA object lives from its declaration until execution leaves its scope.
A C array is a fixed number of objects of one type stored contiguously in memory. Arrays and pointers are closely tied: in most expressions an array name turns into a pointer to its first element, and the subscript a[i] is defined through pointer arithmetic.
C has no separate string type. A string is a sequence of characters terminated by the null character '\0' (value 0), stored in an array of char. Unbounded traversal functions such as strlen need a null terminator within accessible storage.
A structure groups values of different types into one object, such as a student record with a name and marks, or a list node with a key and a pointer to the next node. A union lets several members share the same storage, so that the object holds one of them at a time.
The C standard does not pin down the result of every program. It leaves some choices to the compiler on purpose, so that C can run efficiently on very different machines.