wiki:InsiaProgCIntro

Sommaire

Programmation C - Introduction générale et pratique

1. Historique

  • Créé en 1972 par Thompson et Ritchie pour développer un nouveau système d'exploitation (UNIX).
  • Publié en 1978 par Kernigan et Ritchie
  • Première normalisation en 1990: ANSI C et ISO/IEC 9899:1990 (dite C89 ou C90)
  • Mise à jour importante en 1999: ISO/IEC 9899:1999 (dite C99)

Note: création du langage C++ en 1983.

2. Utilisation

  • Systèmes d'exploitations: Unix (BSD, MACH, Linux, NT, ...)
  • Bibliothèques bas niveau (interface système, imagerie, etc)
  • Embarqué
  • TP !

3. Principes de programmation

Toutes les informations péréiphériques utiles avant même de commencer à programmer en C ...

Le fichier .c

Un programme C est traditionnellement stocké dans un fichier dont l'extension est .c (minuscule). A distinguer des extensions .C, .cxx ou .cpp en général réservées au C++. Il n'y a pas de contrainte particulière sur le nom du fichier (autre que la convention pour son extension).

L'exemple canonique helloworld.c:

#include <stdio.h>

int main(int argc, const char** argv) {
  printf("Hello world !\n");
  return 0;
}

Note aux programeurs C++:

  • la convention CamelCase est peu pratiquée en C, on verra donc beaucoup plus souvent helloworld.c ou hello_world.c que HelloWorld.c.

Le fichier .h

Il s'agit du fichier d'interface, déclarant des variables et fonctions qui sont implémetées par un ou plusieurs fichiers ".c". Ils sont utilisés dans deux cas principaux:

  • Pour utiliser les fonctions d'une bibliothèque (ex: stdio.h)
  • Pour déclarer des fonctions de son propre programme, afin de l'utiliser (en tout ou partie) de façon modulaire

Imaginons par exemple une partie d'un programme qui assure le calcul d'une moyenne. Ceci serait typiquement réalisé à l'aide de la paire de fichiers moyenne.h/moyenne.c. Voici moyenne.h:

#ifndef __moyenne_h__
#define __moyenne_h__

float moyenne(int nb_elt, int* elt);

#endif /* __moyenne_h__ */

Et voici son implémentation, moyenne.c:

#include "moyenne.h"

float moyenne(int nb_elt, int* elt) {
  float somme = 0;
  int i;

  for (i = 0; i < nb_elt; i++)
    somme += elt[i];

  return somme/nb_elt;
}

Notes:

  • Quand on est utilisateur d'une bibliothèque, on n'a en général que les fichiers ".h" à dispositon, l'implémentation étant fournie sous forme compilée (DLL)

Le Makefile

Invoquer le compilateur avec toutes ses options à la main est rapidement une tâche pénible. Elle devient insurmontable lorsque son programme est composé de plusieurs fichiers, car on ne sait plus exactement quelle est la séquence de compilation nécessaire à l'obtention du bon programme.

Le Makefile est un fichier interprété par l'outil make. Il permet d'exprimer les actions élémentaires pour compiler chaque fichier, et laisser make déduire la bonne séquence d'actions. Exemple:

default:
  echo "make helloworld - Compile le programme 'helloworld'"

helloworld: helloworld.o
  gcc -o $(@) $(<)  

%.o: %.c
  gcc -c -o $(@) $(<)

Le compilateur

Le compilateur le plus classique (le plus répandu, le plus portable) est GNU gcc. Il a la particularité d'être un compilateur pouvant à la fois compiler plusieurs langages, et compiler pour des des plateformes matérielles très diverses. Sa version stable actuelle est gcc 4.1.x.

Le compilateur assure les phases de traitement suivantes:

  1. Préprocesseur: il s'agit de simples transformation du texte du programment, principalement des "inclusions" d'interface
  2. Compilation: le programme résultant du préprocesseur est compilé en langage assembleur
  3. Assemblage: la sortie de la compilation est transformée en instructions machines
  4. Edition des liens: les différents fichiers compilés (en instructions machines, dit "fichiers objet") sont rassemblés en un programme ou une bibliothèque (DLL)

En général, les 3 premières phases sont effectuées ensemble et de manière transparente pour le processeur. Il reste alors à piloter la compilation et l'��dition des liens, ce qui est assuré par le Makefile. La règle générale pour compiler un programme est:

  • 1 opération de compilation par fichier .c (préprocesseur + compilation + assemblage)
  • 1 opération d'édition de lien par résultante (programme exécutable, bibliothèque dynamique)

Avec gcc on peut étudier la sortie de chacune de ces phases facilement (dans l'ordre):

$ gcc -E helloworld.c >helloworld.E
$ gcc -S helloworld.c
$ gcc -c helloworld.c

Pour étudier le contenu d'un fichier objet ou d'un programme:

$ objdump -tT helloworld.o
$ nm -D helloworld

Le débogueur

Il s'agit d'un outil permettant de contrôler l'exécution du programme et de l'inspecter en cours d'exécution. Pour pouvoir l'utiliser efficacement, il faut demander au préalable au compilateur d'inclure des informations de debugage directement dans le programme. Ceci permet au debugger de faire les aller-retour entre la structure et les symboles du programme (variables, fonctions, numéro des lignes) et leur représentation machine en cours d'exécution.

Avec gcc, il suffit d'ajouter l'option -g à la phase de compilation pour inclure les informations de debug. On peut alors ensuite tracer et analyser le programme obtenu:

$ gdb helloworld

(gdb) break main
Breakpoint 1 at 0x8048365: file helloworld.c, line 4.
(gdb) run
Starting program: /home/zerodeux/biz/formations/svn/insia/c/tp1/helloworld 

Breakpoint 1, main () at helloworld.c:4
4         printf("Hello world !\n");
(gdb) step
Hello world !
5         return 0;
(gdb) 

Le profileur

Plus rarement utilisé, le profileur permet d'obtenir des statistiques sur l'utilisation des fonctions dans un programme. En général on analyse les informations suivantes:

  • Qui appelle qui ? (le call-graph)
  • Quelles sont les fonctions les plus appelées ?
  • Quelles sont les fonctions dans lesquelles le programme passe le plus de temps ?

De même que pour le débogueur, il faut demander au compilateur d'équiper les fichiers objets avec le code nécessaire pour que le profilage soit effectué au cours de l'exécution du programme. Avec gcc, il s'agit de l'option -pg.

Un programme compilé avec le "profilage" produit un fichier de sortie gmon.out qui peut être analysé avec le programme gmon:

$ gprof helloworld > profile.txt
Last modified 14 years ago Last modified on Nov 6, 2006, 11:06:04 AM