C is the native language of Unix. It has come to dominate systems programming in the computer industry.
Work on the first official C standard began in 1983. The major functional additions to the language were settled by the end of 1986, at which point it became common for programmers to distinguish between "K&R C" and ANSI C.
People use C because it feels faster. If you build a catapult that can hurl a bathtub with someone inside from London to New York, it will feel very fast both on take-off and landing, and probably during the ride, too, while a comfortable seat in business class on a transatlantic airliner would probably take less time but you would not feel the speed nearly as much. ~
One good reason to learn C, even if your programming needs are satisfied by a higher-level language, is that it can help you learn to think at hardware-architecture level. For notes specific to the Plan9's C compiler, see Plan9 C.
Compile
To convert source to an executable binary one uses a compiler. My compiler of choice is tcc, but more generally gcc is what most toolchains will use on Linux.
cc -Wall -o main main.c
#include <stdio.h> #include <stdlib.h> #include <math.h> int count = 10; int add_together(int x, int y) { int result = x + y; return result; } typedef struct { int x; int y; int z; } point; void print_point(point point) { printf("the point is: (%d,%d,%d)\n",point.x,point.y,point.z); } int main(int argc, char** argv) { point p; p.x = 2; p.y = 3; p.z = 4; float length = sqrt(p.x * p.x + p.y * p.y); printf("float: %.6f\n", length); printf("int: %d\n", p.z); print_point(p); return 0; }
Include
Generally, projects will include .h
files which in turn will include their own .c
files. The following form is used for system header files. It searches for a file named file
in a standard list of system directories.
#include <file>
The following form is used for header files of your own program. It searches for a file named folder/file.h
in the directory containing the current file.
#include "folder/file.h"
Data Types
char | 0xff | 0-255 |
short | 0xffff | 0-65535 |
IO
One way to get input into a program or to display output from a program is to use standard input and standard output, respectively. The following two programs can be used with the unix pipe ./o | ./i
o.c
#include <stdio.h> int main() { printf("(output hello)"); return 0; }
i.c
#include <stdio.h> int main() { char line[256]; if(fgets(line, 256, stdin) != NULL) { printf("(input: %s)\n", line); } return 0; }
SDL
cc demo.c -I/usr/local/include -L/usr/local/lib -lSDL2 -o demo
To compile the following example, place a graphic.bmp
file in the same location as the c file, or remove the image block.
#include <SDL2/SDL.h> #include <stdio.h> int error(char* msg, const char* err) { printf("Error %s: %s\n", msg, err); return 1; } int main() { SDL_Window* window = NULL; SDL_Surface* surface = NULL; SDL_Surface* image = NULL; if(SDL_Init(SDL_INIT_VIDEO) < 0) return error("init", SDL_GetError()); window = SDL_CreateWindow("Blank Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN); if(window == NULL) return error("window", SDL_GetError()); surface = SDL_GetWindowSurface(window); SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 0x72, 0xDE, 0xC2)); /* Display an image */ image = SDL_LoadBMP("graphic.bmp"); if(image == NULL) return error("image", SDL_GetError()); SDL_BlitSurface(image, NULL, surface, NULL); /* Draw canvas */ SDL_UpdateWindowSurface(window); SDL_Delay(2000); /* close */ SDL_FreeSurface(surface); surface = NULL; SDL_DestroyWindow(window); window = NULL; SDL_Quit(); return 0; }
Misc
String padding: |Hello |
printf("|%-10s|", "Hello");
Macros
#define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define ABS(a) (((a) < 0) ? -(a) : (a)) #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
Reserved Words
auto | else | long | switch |
break | enum | register | typedef |
case | extern | return | union |
char | float | short | unsigned |
const | for | signed | void |
continue | goto | sizeof | volatile |
default | if | static | while |
do | int | struct | _Packed |
double |
Array of function pointers
void (*fns[3])() = {fn1, fn2, fn3};
Operators Precedence
Precedence | Operator | Description | Associativity |
---|---|---|---|
1 | ++ -- |
Suffix/postfix increment and decrement | Left-to-right |
() |
Function call | ||
[] |
Array subscripting | ||
. |
Structure and union member access | ||
-> |
Structure and union member access through pointer | ||
(type){list} |
Compound literal(C99) | ||
2 | ++ -- |
Prefix increment and decrement[note 1] | Right-to-left |
+ - |
Unary plus and minus | ||
! ~ |
Logical NOT and bitwise NOT | ||
(type) |
Cast | ||
* |
Indirection (dereference) | ||
& |
Address-of | ||
sizeof |
Size-of[note 2] | ||
_Alignof |
Alignment requirement(C11) | ||
3 | * / % |
Multiplication, division, and remainder | Left-to-right |
4 | + - |
Addition and subtraction | |
5 | << >> |
Bitwise left shift and right shift | |
6 | < <= |
For relational operators < and ≤ respectively | |
> >= |
For relational operators > and ≥ respectively | ||
7 | == != |
For relational = and ≠ respectively | |
8 | & |
Bitwise AND | |
9 | ^ |
Bitwise XOR (exclusive or) | |
10 | | |
Bitwise OR (inclusive or) | |
11 | && |
Logical AND | |
12 | || |
Logical OR | |
13 | ?: |
Ternary conditional | Right-to-left |
14 | = |
Simple assignment | |
+= -= |
Assignment by sum and difference | ||
*= /= %= |
Assignment by product, quotient, and remainder | ||
<<= >>= |
Assignment by bitwise left shift and right shift | ||
&= ^= |= |
Assignment by bitwise AND, XOR, and OR | ||
15 | , |
Comma | Left-to-right |