C programming

C is the programming language used for the kernel and C++
the object oriented alternative to C. Both are supported by
gcc.

The
hello wold program

Example 15.1. hello.c

#include <stdio.h>
main()
{
printf("Hello World!\n");
}

To compile it (-o hello produces hello as
output file instead of the default a.out)

gcc -o hello
hello.c

Check that the file hello as the executable permission and
run it

./hello

Hello world split in
two files

If programs are getting bigger, they get split in multiple
file. This has different advantages. A file can be reused
somewhere else. Not every thing has to be recompiled just the
file edited. Here the hello world program split in two
files:

The result is not a running program. The two object files
hello.o and printhello.o are produced. The-c option tells
gcc to do so
and not producing absolute addresses. To get a running
program the object files have to be put together using a
linker. Instead of calling the linker ld directlygcc can be called.

Note

Gccstands for Gnu Compiler Collection and not Gnu
C Compiler. Gcc can be used for different things: C
compiler, assembler, linker, ...

The following command links the two object files into the
program hello:

gcc hello.o printhello.o -o
hello

Now it can be run with

./hello

Interacting with
the parent process

To access the command line parameters and the
environmental variables of the parent process declare main as
follows:

int main(int argc, char *argv[], char *envp[])
{
return(0);
}

argc contains how many parameters are passed. There
is always one, the command line that has called the C
program.

argv[] is an pointer to an array containing all
command line parameters available

envp[] is a pointer to an array containing all
environmental parameters as strings formatted
NAME=value, luckily you do not have to search trough
them, there is a function that gets the values assigned
to the names. Example how to get the hostname:

#include <stdlib.h>
char* host;
host = getenv("HOSTNAME");

The return function exits and gives back a number to
the parent process.

Integrated
development Environments (IDE)

IDE's seem the way to go and the first results might be
quickly be achieved, however when in trouble, the command
line options and concepts have to be understood even when
working with a IDE. Additionally IDE's offer so much
functionality, as automatic documentation, publishing and
archiving code, version control, gui support for various
libraries, debugging, code analyze, multiple language
support, and many or too many more. So often if you open an
IDE you do not get the overview and struggle with the project
files.

emerge
codeblocks for C++ using it works
without autotools and make file. It is a ready to go
environment that works as desired. Libraries have to be
added under Project > Build Options > Linker
Settings where the library name without lib or l has to
be added. Command line arguments can be set under
Project > Set programs arguments. Codeblocks is also
available for Windows.

anjuta is and IDE for gnome

Kdevelop is a very big Integrated Development
Environment (IDE) to create your own programs in
various programming languages and endless options and
features. For small programs the size of the program is
smaller than the size of the makefile that Kdevelop has
created for you and you spend more time troubleshooting
Kdevelop than writing your own program. Maybe the
situation looks different when you are a professional
programmer or you work in a team. For a hobby
programmer, Kdevelop is probably an overshoot.

eclipse has is a huge IDE originally developed for
java, but has all kind of plugins available for any
kind of programming languages.

Or why not keep it simple and use just an editor with
syntax highlighting, gcc and make your makefile (or Makefile)
using an editor. Do not forget to add -g to your makefile to have
the info required to debug in your program. Then compile it
in a console by calling make. This way has the obvious
advantage that you know what is going on and you can
concentrate yourself to the creation of your own program.

working with eclipse the CDT has to be installed, this is
best done via marketplace. Marketplace should be available
under help (if not install marketplace). Then the CDT has to
be found, the Marketplace Yoxos has it. There appear many
packages that are related to CDT with big icons, so it takes
a while to find the small icon of the CDT.

Everything to be seen in eclipse is a Perspective, so open
the C/C++ perspective. When done with it open the Debug
Perspective to test your code.

Makefiles and make

If there is just one c file as the hello.c then make and
makefiles are not useful, since a single gcc call will do
everything. However when there are many different files it is
obviously desired to not compile every file when just one got
changed. However when one got changed, then the onces
depending on the changed one need to compiled as well. The
main goal of the makefile is to write down the dependency and
have the program make to do all necessary but not more. By
the way, make is not restricted to C programming, it can call
other command lines not containing gcc commands.

Note

To know what has changed make looks at the modification
dates of the files, therefore make sure your clock is
running well!

Syntax of the
makefiles

Example makefile created by a text editor and put in the
directory where c and h files reside.

Note

Very important is that the indents are done with the
tab character. Make also sure that you editor really
inserts tab and not spaces.

If some files are in other directories then the
-I option can
be used to pass the path:

-I/<path to
file>

Compilation

To compile, open a shell and go to directory, then type
make.

Per default the destination files of gcc are called
a.out. The option -o selects an other name.

make
clean

Having added the clean section in the makefile as shown
above, the command make
clean cleans the directory from object
files no longer used.

Code
optimization

Finally be aware that gcc is normally used to
emerge <Gentoo
ebuilds> and is therefore
set to produce code optimized for speed. The variables
defined in /etc/make.conf are
passed to gcc, so check those options

Those options are OK, but the -fomit-frame-pointer
produces long reaction time when you debug your c program.
Therefore you might consider to change /etc/make.conf while you are in a longer
debug session.

Built runnable binaries can be copied to /usr/local/bin to be used outside of the
development environment. Better would be putting just links
there to your executable and add a version number to your
executable file name. So you are prepared for new versions.
However you should not copy executables manually, you
should install them following the rules of your Linux
distribution to not make a mess. For Gentoo this means you
should write an ebuild.

Debugging

I don't think you want to debug in a console, so use a
front end for dgb the console debugger. By the way, also the
big development environments as Kdevelop are no more than a
front end for gdb when it comes to debug.

Make sure you complied it with the option -g that adds
information for the debugger into the executable. Executables
under Linux are not just raw program code, as used in
embedded systems and other operating systems, they are
formatted elf files. Elf files have different section and
using the -g option the debugging section is added. To
observe the hello executable:

readelf --all
hello

objdump -h
hello

Maybe make refuses to recompile after just editing the
makefile, so edit the source file or delete the
executable.

gdb

to debug in the console start gdb by gdb<my
program>

Then type some commands as:

Table 15.1. gdb

run

run the program until it exits, finds a break
point or error

print
<variable
name>

show contents of a variable

quit

quit gdb

break
<function
name>

set a breakpoint to a function

next

single step

nexti

single step

help

show help

Nemiver

Is what it should to be a modern easy to go and
intuitive gui debugger

Insight

Insight is an other front-end for gdb. It uses tk.tcl
and wants it in a certain location, otherwise it fails.

ddd

An other front-end for gdb is ddd. It is rather ugly and
not intuitive. To debug an executable it has to be called
in command line ddd<name of
executable>. Even it is ugly
it works well.

Execution from the
text console

To execute a program type ./<filename> ./ is your
current directory so bash finds the executable.

Libraries

Using
Libraries

To use Libraries include

#include <math.h>

to the source code, but this might not be enough.

/usr/lib contains the
mathematic library libm. To use it with gcc you must tell
gcc by adding
-lm that you
want it. -l stands for including libraries and m is the
short name of libm, where lib gets wiped off. So the gcc
command line in the makefile becomes:

gcc -g <source>.c
-lm -o <source>

This has to be done for all libraries. The only
exception is glibc the global C library.

For the libncurses add: -lcurses

For libraries not in /usr/lib the option -L can be used to tell
gcc where they are.

-L /usr/X11R6/lib

Instead of finding out where the libraries are and use
this hard coded pkg-config can be used. It will be
available after emerge
pkgconfig. To see what it does call it
as:

pkg-config --libs --cflags
modbus and when you have libmodbus
installed you get: -lmodbus

Creating Libraries

If code is used again and again, then it is time to put
it into a library and make it easily available. The code is
compiled as usual with the -c option so the linker will not
be involved. The following shows how the split hello world
program makes use of a library:

gcc -c
printhello.c

The output is a object file printhello.o. A number of
such files can be added into a library archive
<library>.a

ar r<library>.a
<code1>.o
<code2>.o

For the printhello.o the command looks as:

ar r libhello.a
printhello.o

After running ar, ranlib can be used to add
an index of the contents to the file to speed up its
use.

ranlib
libhello.a

Using the following commands the content of a library
can be observed

ar t
libhello.a

nm -s
libhello.a

After having the library it can be used as:

gcc -o hello hello.c
libhello.a

or

gcc -o<program>
<program>.c /<path to>/<library>.a

or as standard libraries in /usr/lib but telling with -L where the
library is

gcc -o<program>
<program>.c -L/<path to library>
-l<library-lib>

or for the hello world

gcc -o hello hello.c
-L/<path>
-lhello

Note, that using this commands the library code is
inserted to the program, therefore it is called statically
linked libraries. With each program using the library code,
a copy of the library code is loaded into the memory.

Dynamic linked
libraries

Statically linked libraries can reside multiple times in
the memory. More ideal would be loading the library into
memory with the first program demanding it and then share
it with all demanding programs. This is the concept of the
dynamically linked libraries. Those files end with .so
(shared object) suffixes in their names.

Since the library and program are separate files there
is a potential for a version conflict. Additionally
dynamically linked libraries must be known by the operating
system, this is an additional potential to run in
troubles.

Version numbers are added to the files. To have a
certain flexibility when the version numbers do not match
exactly, there is a major and a minor version number. The
shared object files appear therefore in multiple forms:

realname

/usr/lib/libhello.so.1.0

Holds the code and is therefore the shared
object file

soname

/usr/lib/libhello.so.1

Is a link to realname and allows an
evolution

linkername

/usr/lib/libhello.so

Name that the linker uses

When the program gets loaded by the run-time linker,
/lib/ld.so or /lib/ld-linux.so, Linux needs to know where
the library is, this information comes out of the linker
cache /etc/ld.so.conf that is
a binary file and ldconfig updates it. The directories
where shared objects are to be expected are listed in:
/etc/ld.so.conf. If it will not be found in the linker
cache (where just the most recent are) then it will scan
certain directories.

The addresses where the code in dynamically linked
libraries are placed can not be fixed. Therefore Position
Independent Code (PIC) is required that is created with the
gcc option -fPIC. To build a shared object compile the code
as:

gcc -fPIC -c
printhello.c

Then link it to a shared object

ld -shared -soname
libhello.so.1 -o libhello.so.1.0 -lc
printhello.o

then as root, copy libhello.so.1.0 to /usr/lib, /lib or /usr/local/lib>

create necessary links and cache

ldconfig -v
-n

Now an application to test the shared object is
necessary. Assuming the shared object has been put in
/usr/lib the following
command applies:

gcc -o hello hello.c
-L/usr/lib -lhello

And now it can be tested:

./hello

To observe what the system knows about it and to get
information when trouble shooting, the following commands
can be used: