After so many years and decades, the world is still powered by the C programming language. Here are some source codes written entirely in C (the ANSI standard).
All the source files have been tested to compile and execute. All of them are written on Emacs. They are compiled and executed on bash. See the list of all source files below in contents
section. The source files are commented well. This should help any new learner of C and anyone else in general. A reference card is here.
On bash, the source io.c can be compiled using gcc
as follows:
gcc -o io io.c
A new executable file with the name io
will be created in the same directory. Do the same for other source files.
The executable file io
which was created in the compilation step can now be run (executed) as follows:
./io
Do the same for other executables.
Ideally, the compilation shouldn't generate any errors. However, compiling some source files such as containers.c might generate an error due to math.h
header file. In this case, compile as follows:
gcc -o containers containers.c -lm
Do the same for any source file that includes math.h
as a header file.
Source | Topics |
---|---|
preludes.c | Conversions, operators, typedef |
flow.c | Statements, if else , switch , loops, jumps |
containers.c | C containers: arrays, structures, unions, pointers |
methods.c | Functions: declaration, definition, by value, by pointer, recursion, variable arguments, function pointers |
io.c | Standard I/O, file I/O, read and write strings |
preprocessor.c | Preprocessor directives: unconditional and conditional, parametrized macros, standard macros |
library.c | time.h , unistd.h |
Some tips and rules of thumb on writing efficient C code would be:
And as such, their use should be minimized. For example, function call require two jumps and as such, short functions should be replaced by inline
functions.
Iteration should be preferred over recursion.
Replace long if else if
chain with a switch
. The compiler sometimes optimizes the switch into some table lookup with a single jump. If a switch is not possible, put the most likely clause (or common clauses) at the beginning of the 'if' chain.
Move loops inside function calls. For example, instead of writing
for (i = 0; i < 10; i++) DoSomething();
write the following instead
DoSomething() {
for (i = 0; i < 10; i++) { ... } }
Reduce the number of local variables. They are normally stored on the stack. If there are few, they can be stored in registers in which case, the function gets the benefit of the faster memory access of data stored in registers and avoids the overhead of setting up a stack frame.
Reduce the number of function parameters. Because of the same reason as above — they are stored on stack.
When declaring object variables, use initialization instead of assignment. For example,
Color c(black);
is more efficient than
Color c; c = black;
Delay declaring local variables.
Use the smallest possible data type. In most cases, an unsigned int
(usually 4 bytes) or even unsigned short
(usually 2 bytes) gets the job done.
If you do not need a return value from a function, do no define one.
Make default class constructors as lightweight as possible.
Wherever possible, replace multiplication by shift operations >>
and <<
.
For most classes, use the operators +=, -=, *=, and /= instead of the operators +, -, *, and /.
For basic data types, use the operators +, -, *, and / instead of the operators +=, -=, *=, and /=.
For objects, use the prefix operator (++obj) instead of the postfix operator (obj++). A copy of the object must be made with the postfix operator (which thus involves an extra call to the constructor and destructor), whereas the prefix operator does not need a temporary copy.
More source files shall be added soon. Some of the existing code shall be also updated. More tips on writing efficient C code shall be added.