🕒 : 3 h maximum

Prérequis:


But:

  • prise en main de la chaîne de compilation pour faire du c ansi avec GCC
  • Afficher un caractère (char)
  • Afficher une chaîne de caractère (string)
  • utilisation de gdb , pas à pas .
  • Afficher une valeur entière et comprendre les limites des variables (char, int , long )

Répertoire du travail:

~/Works/TP0_C

etudiant@ordi:~/Works$ tree TP0_C/
TP0_C/
├── bonjour
│   ├── bonjour
│   └── bonjour.c
└── limits
    ├── limits
    └── limits.c

2 directories, 4 files
etudiant@ordi:~/Works$

1 – Bonjour le monde !

Donc si vous avez bien écouté et compris, sur votre ordinateur vous disposez d’un répertoire TP0_C dans votre répertoire Works de votre espace de travail.

🔔 Rappel : cd ou cd ~ vous amène dans votre espace de travail ou que vous soyez

mkdir pour make directory .. si vous avez oublié …c’est grave attention !

Donc nous sommes actuellement dans le répertoire du TP0_C ok

Créer un répertoire projet bonjour.

pour créer le répertoire bonjour !

mkdir bonjour

dans ce répertoire recopier le code suivant : bonjour.c

/***********************************/
/* Code en c de bonjour le monde ! */
/*                                 */
/* Date: 27/06/2025                */
/* Auteur: BoGt                    */
/***********************************/
#include <stdlib.h>
#include <stdio.h>

int main()
{
	printf("Bonjour le monde ! \n");
	return EXIT_SUCCESS;
}

on peut noter /* et */ encadre du commentaire en c Ansi , beaucoup pensent à tort que les commentaires ne sont pas utile car effectivement ils ne font pas mieux fonctionner votre code ! Mais nous ne sommes pas des machines , les commentaires sont la pour nous aider à mieux poser nos idées , et à mieux communiquer nos idées. C’est une qualité à bien développer pour un codeur !

Par exemple , ici on sait ce que fait notre code , et qui l’as produit et quand…. pas du luxe ! La notation de vos codes en dépendra pour pas mal de points. Prenez de bonnes habitudes ! ne pas s’en priver !

1-1 Saisir le code avec vi

il faut avoir lu le cours vi et le tp vi.

1-2 Compiler et corriger votre code c (normalement pas besoin !)

Saisir le code c , bonjour.c .

vous disposez d’un fichier bonjour.c (comme celui ci-dessus) dans votre répertoire Works/TP0_C

pour le compiler comme vu dans le cours de c de gcc il faut transformer le langage c en langage compréhensible par la machine, pour simplifier le langage c appelé langage évolué en langage machine des 0 et des 1 …que le processeur va bien comprendre!

ici dans notre apprentissage on est sur des processeurs de la famille INTEL (constructeur) X86. Le premier PC (personnal computeur) IBM etait fabriqué avec un 8086, qui a bien évolué avec le temps. Les ordinateurs PC ont une compatibilité ascendante. Les programmes du premier PC doivent toujours fonctionner sur le dernier core I9 ….de Intel, et je n’évoque pas les clones de AMD…

on appel cette phase la compilation:

gcc bonjour.c -o bonjour -Wall -ansi -pedantic -lc -g

les options de compilation

  • -Wall , pour Warning All
  • -ansi pour n’accepter que du code ansi
  • -pedantic ,pédagogique va vous forcer à écrire un code pédagigique .
  • -g pour pouvoir utiliser le débugger (l’outil du codeur)

mais vous pouvez vous créer quelques erreurs et voir les messages, et corriger !

ls -l
total 28
-rwxrwxr-x 1 bruno bruno 15960 juin  29 17:55 bonjour
-rw-rw-r-- 1 bruno bruno   132 juin  29 17:54 bonjour.c
➜  bonjour 

Quand la phase de compilation se passe bien , c’est à dire que gcc (le compilateur) comprend votre code sans aucune indétermination ou ambiguïté

si il ne comprends pas il va vous noter une erreur , sinon un warning (attention) et c’est qu’il aura pris une décision à votre place et c’est pas bon ! car ici l’humain doit décider vu que c’est son idée! pas celle de la machine !

compiler sans l’option -g et avec , comparer la quantité en octets de vos executables. (ls -l)

Donner une explication !

1-3 utilisation de gdb

Ici nous allons découvrir cet outil puissant qu’est gdb , gnu debugger .

il faut absolument compiler avec l’option -g , sinon le debugger n’a pas la main sur votre code ! -g va mettre des sondes logicielles pour pouvoir gérer le code .

etudiant@ordi:~/Works/TP0_C/bonjour$ gdb bonjour
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04.2) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from bonjour...
(gdb) l
1       /***********************************/
2       /* Code en c de bonjour le monde ! */
3       /*                                 */
4       /* Date: 27/06/2025                */
5       /* Auteur: BoGt                    */
6       /***********************************/
7       #include <stdlib.h>
8       #include <stdio.h>
9
10      int main()
(gdb) l
11      {
12              printf("Bonjour le monde ! \n");
13              return EXIT_SUCCESS;
14      }
(gdb)

on a utilisé la commande list (l) pour voir ici avec colorations syntaxique notre code source (le .c)

1-4 run de gdb

(gdb) run
Starting program: /home/etudiant/Works/TP0_C/bonjour/bonjour
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Bonjour le monde !
[Inferior 1 (process 14000) exited normally]
(gdb)           

le run execute le code ! et on remarque que le code se termine normalement !

on constate que gdb charge librairie dynamique libthread_db.so.1 dont ici nous n’avons que faire !

notre chaîne s’affiche bien comme voulu avec le retour à la ligne !

1-5 Breakpoint (br)

(gdb) br main
Breakpoint 1 at 0x555555555151: file bonjour.c, line 12.
(gdb)

breakpoint , point d’arrêt ! la contraction plus rapide à taper est br .

ici on a placé un point d’arrêt à la ligne 12 en indiquant le non de la fonction ou on veut s’arrêter. br 12 aurait eu le même résultat.

ici c’est dans la mémoire à l’adresse: 0x555555555151

1-6 run avec un point d’arrêt.

(gdb) br main
Breakpoint 1 at 0x555555555151: file bonjour.c, line 12.
(gdb) run
Starting program: /home/etudiant/Works/TP0_C/bonjour/bonjour
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at bonjour.c:12
12              printf("Bonjour le monde ! \n");
(gdb)

on arrive avant l’exécution de la ligne 12. gdb attend vos ordres!

1-7 next

Breakpoint 1, main () at bonjour.c:12
12              printf("Bonjour le monde ! \n");
(gdb) n
Bonjour le monde !
13              return EXIT_SUCCESS;
(gdb)

n pour next , possible aussi s comme step ! mais on verra par la suite qu’il y a une différence , next, ligne suivante ..step avance ..

vous pouvez terminer le programme avec des nexts…

1-8 exit

pour sortir de gdb et revenir à bash

2- les limites.

dans un répertoire limits

la fonction sizeof nous donne la quantité en octets de la variable passé en argument.

2-1 le code limits.c

limits.c:

#include <stdio.h>
#include <stdlib.h>  /* pour EXIT_SUCCESS, EXIT_FAILURE */

int main() {

        printf("Taille de char            : %lu octet(s)\n", sizeof(char)); /* %lu long unsigned */                                                                        
        printf("Taille de signed char     : %lu octet(s)\n", sizeof(signed char));
        printf("Taille de unsigned char   : %lu octet(s)\n", sizeof(unsigned char));

        printf("Taille de short           : %lu octet(s)\n", sizeof(short));
        printf("Taille de unsigned short  : %lu octet(s)\n", sizeof(unsigned short));

        printf("Taille de int             : %lu octet(s)\n", sizeof(int));
        printf("Taille de unsigned int    : %lu octet(s)\n", sizeof(unsigned int));

        printf("Taille de long            : %lu octet(s)\n", sizeof(long));
        printf("Taille de unsigned long   : %lu octet(s)\n", sizeof(unsigned long)); 

        return EXIT_SUCCESS;
}
etudiant@ordi:~/Works/TP0_C/limits$ vi limits.c
etudiant@ordi:~/Works/TP0_C/limits$ gcc limits.c -o limits -Wall -ansi -pedantic -g

on teste le code

compiler avec les options -ansi , -Wall , pedantic , -g

etudiant@ordi:~/Works/TP0_C/limits$ ./limits
Taille de char            : 1 octet(s)
Taille de signed char     : 1 octet(s)
Taille de unsigned char   : 1 octet(s)
Taille de short           : 2 octet(s)
Taille de unsigned short  : 2 octet(s)
Taille de int             : 4 octet(s)
Taille de unsigned int    : 4 octet(s)
Taille de long            : 8 octet(s)
Taille de unsigned long   : 8 octet(s)
etudiant@ordi:~/Works/TP0_C/limits$

2-2 donner les valeurs max et min de tous les types vu dans ce code

on rappel qu’un octet c’est 8 bits!

pour comprendre le codage complément à 2 .

donner un calcul pour chaque type , unsigned (non signé)..

on peut s’aider du fichier /usr/include/limits.h (pour vérifier)

3- Votre travail final doit ressembler à :

ne pas oublier de sauvegarder sur linux3!

etudiant@ordi:~/Works$ tree TP0_C/
TP0_C/
├── bonjour
│   ├── bonjour
│   └── bonjour.c
└── limits
    ├── limits
    └── limits.c

2 directories, 4 files
etudiant@ordi:~/Works$