Every type in c is either an object or a function type.
Variables have a declared type that tells you the kind of object at it's
value. This is important because a collection of bits will likely have a
different value with a different type. For example, the number 1 is represented
in IEEE 754 (floating-point arithmetic standard) by the bit pattern
0x3f800000. If you were to interpret that same bit pattern as an int, you'd
get the value 1,065,353,216 instead of 1.
Boolean
The _Bool type was introduced in C99 and can store 1 or 0. It starts with
an underscore because all identifiers begining with underscores are reserved.
However, it's generally better to use the bool type in <stdbool.h> which can
be assiged true or false (which expand to integer constants 0 and 1).
#include <stdbool.h>
_Bool flag1 = 0;
bool flag2 = false;
Character
The C language defines three character types: char, signed char and
unsigned char. Compilers will define char to have the same alignment, size,
range, representation, and behavior as either signed or unsigned char.
Regardless, char is still a separate type and is incompatible with both. It's
commonly used to represent character data, but is only big enough for ascii.
There were attempts at adding "wide character" suppport to C with wchar_t, but
most people use a proper unicode library. This one is small and efficient:
https://libs.suckless.org/libgrapheme/
Enumeration
An enum allows you to define a type that assigns names to integer values in
cases with an enumerable set of constant values:
enum day { sun, mon, tue, wed, thu, fri, sat };
enum cardinal_points { north = 0, east = 90, south = 180, west = 270 }
enum months { jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec }
The values are automatically indexed by 0 and incremented by one unless manually
defined (see months). Duplicate values can exist and the actual value of the
enumeration constant is implementation defined. For example, Visual C++ uses a
signed int while GCC uses an unsigned int.
Void
The keyword void by itself means "cannot hold any value." For example, you can
use it to indicate that a function does not return a value, or as the sole
parameter to indicate that it takes no arguments. On the other hand void *
means that the pointer can reference any object.
Integer
Signed integers can be negative, zero, or possitive; unsigned may only be zero or possitive. The range that each type of integer can represent depends on the implementation.