Go Back

C Basics

Quick syntax crash course in C

In C, declarations follow a pattern of type followed by a name such as:

C also requires you to end statements with the semicolon ;


int main(void)
{
//code goes here
}

Here, int is the return type (integer) main is the function name. The parameter void just says that a function does not take parameters

Declarations of variables are done in the same order


int x;
int y = 0;
int a, b, c;
a = 3;
b = 4; c = 5;

These show different ways of declaring and assigning

Some C standards might require you to declare first (pre C99, such as C89). For example


int i, n;

n = 16;
for (i = 0; i < n; i++){
	//do stuff
}

But in C99 and later, you can declare it with the for loop


int n = 16;
for (int i = 0; i < n; i++){
	//do stuff
}

In C, you can increment a variable with pre or post increment.


int i = 0;
bool greater = ++i == 0; //this is false, the variable is incremented first, and then compared
bool equal = i++ == 1; //this is true, the variable is compared first, and then incremented

More on for loops

For loops look quite innocuous in C, but you can do some really weird things with them that you can't in other languages, or things that are not as obvious

For example


for (int i = 0; loop_should_end(); i++){//do stuff}

Let's say the loop_should_end() function returns a bool (0 or 1). The return result decides if the loop continues or not.

Any kind of non-zero value keeps the loop going, while a 0 terminates the loop

Something that will look really wild is this


for (int i = 0; i < 16; i++, some_function()){//do stuff}

In C, you can give the third argument one other statement. The third argument (or arguments in this case) is executed after one iteration finishes

While loops and Do While loops

These are pretty simple and don't have any extras (like the for loop)


while(condition){//do stuff}
while(condition);//executes until condition is false, and it's usually used to increment something up to some sentinel value / terminator.

do{
	//do stuff
}while(condition); //this semicolon is needed here.

Function, Structs and Enum Declarations

You can declare function signatures in C, like in other languages, as such:


int myfunc(int a, int b);
static int funcA(void); //visible inside its current file only
inline int funcB(void); //inline (C99+, or through compiler internals) suggests to the compiler to inline the function. It can work with the static keyword too.


int bar(void)
{
	//this will not work and will throw a compiler error, because scoped_func is declared after this function
	scoped_func();
}

int foo(void)
{
	int arg = 0;

	//function signature. This tells the compiler that there exists some function called scoped_func, and that is its signature.
	void scoped_func(int a);

	//this will work, because the function signature exists in this scope, even if it is forward declared
	scoped_func(arg);
}

//forward function declaration
void scoped_func(int a)
{
	//do stuff
}

Struct and Enum declarations are similar to each other:


struct Point{
	int	x;
	int	y;
};

struct Pointf{
	//they can also be declared together
	float	x, y;
};

enum ColorType{
	RED, //auto-increments as any other language
	GREEN,
	BLUE
};

enum TokenType{
	BRACKET_OPEN = 55, // you can also start from an arbitrary place
	BRACKET_CLOSE,
	PAREN_OPEN = 60, // you can change a value and ignore the auto-increment
	PAREN_CLOSE, //auto-increment resumes here
};

Preprocessor Macros

Most of the time, you will use #include and #define macros

The former will paste a file into the current file, and the latter will declare some code to some name

For example:


#include "myfile.h" //this will literally paste the contents of myfile.h into the current file
#include <stdio.h> //the angle-bracket is used to tell the compiler that the target directory is in /usr/includes ( for Linux )
#define MAX_LEN 64 //wherever MAX_LEN is used, it will be 64

static int array_a[MAX_LEN]; //it will paste 64 in here
static float array_b[MAX_LEN]; //it will paste 64 in here

Any code works in a #define such as:


#include "myfile.h" //this will literally paste the contents of myfile.h into the current file
#include <stdio.h> //the angle-brackets tell the compiler to search system include paths (like /usr/include on Linux)
#define min(a, b) ((a) < (b) ? (a) : (b)) //ternary operator "?" works like in other languages
#define max(a, b) ((a) > (b) ? (a) : (b))

int main(void)
{
	int a, b;
	float i, j;

	a = 3; b = 5;
	i = 5.5; j = 6.5;

	float resultf = max(i, j); //this will result in j
	int resulti = min(a, b); //this will result in i
}

To put multiple lines of code in a #define you do as follows:


//notice the backslash "\" at the end. Also, there cannot be any spaces
#define FIELDS \
	float x, y;\
	int width, height;

//Just as an example, this will paste in the text, line by line, as you wrote it.
struct Rectangle{
	FIELDS
};

That's enough introduction to the syntax and declarations. Next, I'll go into a very important first step: String Parsing and Memory Management