Algorithmes et C appliqués aux Systèmes Numériques
                
                           Les appels systèmes, les erreurs et la chaine de compilation  
                        John Samuel 
                          CPE LyonAnnée : 2022-2023Courriel : john(dot)samuel(at)cpe(dot)fr
                        
                
                              
		 
		
	 
	
		
		
			Objectifs 
			
				La portée des variables 
				Préprocesseur 
				Les appels systèmes 
				Les erreurs 
				La chaine de compilation 
			 
		 
		
	 
	
		
		
                        Une variable constante 
                        
			  
				/* Une variable constante
				#include  <stdio.h> int  main () { const int  year  = 2017 ; // une variable constante
                 year  = 2019 ; // tentative de modification d'une variable constante
                 printf ("C'est l'annee %d" , year ); return  0;
                
         
        
     
    
        
        
            Erreur pendant la compilation 
            
                $ gcc bonjour.c
                          const.c: In function ‘main’:
                          const.c:5:8: error: assignment of read-only variable ‘year’
                          year = 2019;
                          
            
         
        
     
    
        
        
            Une variable globale 
            
                
				/* affiche un message à l'écran en utilisant une variable globale
				#include  <stdio.h> int  year  = 2017  // une variable globale;
				int  main ()
				{ printf ("C'est l'annee %d" , year ); //affiche 2017return  0;
            
         
        
     
    
        
        
            Une variable globale 
            
                
				/* affiche un message à l'écran en utilisant une variable globale
				#include  <stdio.h> int  main ()
				{ printf ("C'est l'annee %d" , year ); return  0;int  year  = 2017  // une variable globale;
			
            
         
        
     
    
        
        
            Erreur pendant la compilation 
            
                $ gcc bonjour.c
bonjour.c: In function ‘main’:
bonjour.c:5:30: error: ‘year’ undeclared (first use in this function)
    5 |   printf("C'est l'annee %d", year);
      |                              ^~~~
bonjour.c:5:30: note: each undeclared identifier is reported only once for each function it appears in
                          
            
         
        
     
    
        
        
            Une variable locale 
            
                
				/* affiche un message à l'écran en utilisant une variable locale
				#include  <stdio.h> int  year  = 2017  // une variable globale;
				int  main ()
				{ int  year  = 2018  // une variable locale; printf ("C'est l'annee %d" , year ); //affiche 2018return  0;
            
         
        
     
    
        
        
            Une variable locale 
            
                
				/* affiche un message à l'écran en utilisant une variable locale
				#include  <stdio.h> int  year  = 2017  // une variable globale;
				int  main ()
				{ int  year  = 2018  // une variable locale; int  year  = 2019  // une variable locale; printf ("C'est l'annee %d" , year ); //affiche 2019printf ("C'est l'annee %d" , year ); //affiche 2018return  0;
            
         
        
     
    
        
        
            1. Passage par valeur 
            
                
                        void 
                        echange(
                        int 
                        a ,
                        int 
                        b 
                        ) { 
                          int 
                        temp 
                        = a ;
                          a 
                        = b ;
                          b 
                        = temp ;
                        }
                                  int  main ()
				{ int  a  = 10;
                          int  b  = 20;
                          echange (a , b );
				   printf ("a: %d, b: %d" , a , b ); //affiche 10, 20return  0;
            
         
        
     
    
        
        
            2.1 Passage par référence: une variable 
            
                
                        void 
                        echange(
                        int 
                        *a ,
                        int 
                        *b 
                        ) { 
                          int 
                        temp 
                        = *a ;
                          *a 
                        = *b ;
                          *b 
                        = temp ;
                        }
                                  int  main ()
				{ int  a  = 10;
                          int  b  = 20;
                          echange (&a , &b );
				   printf ("a: %d, b: %d" , a , b ); //affiche 20, 10return  0;
            
         
        
     
    
        
        
            2.2. Passage par référence: un tableau 
            
                
                        void 
                        affichage(
                        char 
                        message[10] 
                        ) { 
				   printf ("%s\n" , message ); 
                        }
                                  int  main ()
				{ char  message[10]  =
			"Bonjour" ;
                          affichage (message );
					   return  0;
            
         
        
     
    
        
        
            2.2. Passage par référence: un tableau 
            
                
                        void 
                        affichage(
                        char 
                        message[] 
                        ) { 
				   printf ("%s\n" , message ); 
                        }
                                  int  main ()
				{ char  message[10]  =
			"Bonjour" ;
                          affichage (message );
					   return  0;
            
         
        
     
    
        
        
            2.2. Passage par référence: un tableau 
            
                
                        void 
                        affichage(
                        char 
                        *message 
                        ) { 
				   printf ("%s\n" , message ); 
                        }
                                  int  main ()
				{ char  message[10]  =
			"Bonjour" ;
                          affichage (message );
					   return  0;
            
         
        
     
    
        
        
            2.2. Passage par référence: un tableau 
            
                
                        void 
                        affichage(
                        int 
                        tableau[2][2] 
                        ) { 
				  for  ( int  i  = 0;
					i  < 2; i ++) {for  ( int  j  = 0;
					j  < 2; j ++) {printf ("%d\n" ,
				 tableau [i ][j ]);
					    }
					  }
                        }
                                  int  main ()
				{ int  prix [2][2] = {affichage (prix );
					   return  0;
            
         
        
     
    
        
        
            2.2. Passage par référence: un tableau 
            
                
                        void 
                        affichage(
                        int 
                        tableau[][] 
                        ) { 
				  for  ( int  i  = 0;
					i  < 2; i ++) {for  ( int  j  = 0;
					j  < 2; j ++) {printf ("%d\n" ,
				 tableau [i ][j ]);
					    }
					  }
                        }
                                  int  main ()
				{ int  prix [2][2] = {affichage (prix );
					   return  0;
            
         
        
     
    
        
        
            2.2. Passage par référence: un tableau 
            Erreur pendant la compilation 
            
                $ gcc tableau.c
tableau.c:3:21: error: array type has incomplete element type ‘int[]’
    3 | void affichage( int tableau[][] ) {
      |                     ^~~~~~~
tableau.c:3:21: note: declaration of ‘tableau’ as multidimensional array must have bounds for all dimensions except the first
tableau.c: In function ‘main’:
tableau.c:15:13: error: type of formal parameter 1 is incomplete
   15 |   affichage(prix);
                          
            
         
        
     
    
        
        
            2.2. Passage par référence: un tableau 
            
                
                        void 
                        affichage(
                        int 
                        tableau[][2] 
                        ) { 
				  for  ( int  i  = 0;
					i  < 2; i ++) {for  ( int  j  = 0;
					j  < 2; j ++) {printf ("%d\n" ,
				 tableau [i ][j ]);
					    }
					  }
                        }
                                  int  main ()
				{ int  prix [2][2] = {affichage (prix );
					   return  0;
            
         
        
     
    
        
        
            2.2. Passage par référence: un tableau 
            
                
                        void 
                        affichage(
                        int 
                        (*tableau)[2] 
                        ) { 
				  for  ( int  i  = 0;
					i  < 2; i ++) {for  ( int  j  = 0;
					j  < 2; j ++) {printf ("%d\n" ,
				 tableau [i ][j ]);
					    }
					  }
                        }
                                  int  main ()
				{ int  prix [2][2] = {affichage (prix );
					   return  0;
            
         
        
     
    
        
        
            2.2. Passage par référence: un tableau 
            
                
                        void 
                        affichage(
                        int 
                        **tableau ,
                        int 
                        lignes ,
                        int 
                        colonnes 
                        ) { 
				  for  ( int  i  = 0;
				i  < lignes ; i ++) {for  ( int  j  = 0;
				j  < colonnes ; j ++) {printf ("%d\n" ,
				 tableau [i ][j ]);
					    }
					  }
                        }
                                  int  main ()
				{ int  **prix , lignes , colonnes ;
				  ....
                          affichage (prix ,
                        lignes ,
                        colonnes );
					   return  0;
            
         
        
     
    
        
        
            
                
                    un tableau à deux indices 
                 
             
         
        
     
    
        
        
            Passage par référence: un tableau 
            
                
                          int  main ()
                         { 
				  int  **tableau , lignes  = 2, colonnes  = 10;
				  tableau  = calloc (sizeof(int  *), lignes );
				  for  ( int  i  = 0;
				i  < lignes ; i ++) {tableau [i ] = calloc (sizeof(int ), colonnes );
					  }
				  for  ( int  i  = 0;
				i  < lignes ; i ++) {for  ( int  j  = 0;
				j  < colonnes ; j ++) {tableau [i ][j ] = i+j;
					    }
					  }
				  ...
			
            
         
        
     
    
        
        
            Passage par référence: un tableau 
            
                
				  ...
                          affichage (tableau ,
			                     lignes ,
					     colonnes );
				  for  ( int  i  = 0;
				i  < lignes ; i ++) {free (tableau [i]);
					  }
				  free (tableau );
					   return  0;
            
         
        
     
    
        
        
            
cercle.c 
            #define  PI 3.14159
			float  area (
			float  radius ) { return (PI * radius 
						* radius ); 
    
        
        
            Prototype (defs.h) 
            
			#define  PI 3.1415926535
            cercle.c 
            
				#include  "defs.h" #ifndef  PI // Si PI n'est pas défini#define  PI 3.14159#endif float  area (
					float  radius ) { return (PI * radius 
						* radius );
            
                Remarque 1:  PI n'est pas une variable
                Remarque 2:  Utilisez l'option  gcc -E   pour comprendre l'objectif d'un préprocesseur
            
         
        
     
    
        
        
            Prototype (defs.h) 
            
                Erreur:  PI n'est pas une variable
            
            
				#include  "defs.h" #ifndef  PI #define  PI 3.14159#endif float  area (
					float  radius ) { return (PI * radius 
						* radius );
            Erreur (compilation) 
            
                        Error: lvalue required as left operand of assignment
                        PI = 3.15;
                           ^
		 	
         
        
     
    
        
        
            
operators.h 
            
                                int 
                                add(
                                int ,
                                int ); 
            L'utilisation 
            
		        #include 
                        "operators.h"  // en-têtes(headers) #include 
                        "operators.h"  // pas d'erreurs 
        
        
     
    
        
        
            
operators.h 
            
                                int 
                                num  = 20; 
            L'utilisation 
            
		        #include 
                        "operators.h"  // en-têtes(headers) #include 
                        "operators.h"  // erreur 
            
                        $ gcc operator.c
                        note: previous definition of ‘num’ was here
                        int num=20;
		 	
        
        
     
    
        
        
            
operators.h (bonne pratique) 
            
				#ifndef  __OPERATORS_H__ #define  __OPERATORS_H__ int 
                                num  = 20; int 
                                add(
                                int ,
                                int ); #endif  //__OPERATORS_H__
		 	
            L'utilisation 
            
		        #include 
                        "operators.h"  // en-têtes(headers) #include 
                        "operators.h"  // 2eme fois, mais pas d'erreurs 
        
        
     
    
        
        
            
				#ifndef  PI #define  PI 3.14159#endif #ifndef  square #define  square(value) value * value#endif float  area (
					float  radius ) { return (PI * square(radius) );
            
                Remarque:  Il'n y a pas d'espace entre square et (
            
         
        
     
    
        
        
            
                Source: https://commons.wikimedia.org/wiki/File:AdditiveColorMixiing.svg 
             
         
        
     
    
        
        
            
                          struct  couleur1{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
                        };
			
            
                          struct  couleur2{ 
                           unsigned char  rouge;
			   unsigned int   count;
                           unsigned char  vert;
                           unsigned char  bleu;
                        };
			
            
                           printf (
                          "size- couleur1: %lu, couleur2: %lu\n" , 
                            sizeof (
                          struct 
                          couleur1 ),
                          sizeof (
                          struct 
                          couleur2 ));
			
            
                Question:  Quel est l'affichage de ce programme?
            
         
        
     
    
        
        
            Alignement d'un octet 
            
                couleur1 
             
            
                couleur2 
             
         
        
     
    
        
        
            Alignement de 4 octets 
            
                couleur1 
             
            
                couleur2 
             
         
        
     
    
        
        
            Alignement en utilisant gcc 
            
                 
         
        
     
    
        
        
            En utilisant gcc 
            
                          #pragma pack(push) 
                          #pragma pack(1)  //alignement d'un octet
                          struct  couleur3{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
                        };
                        #pragma pack(pop) 
                           printf (
                          "%lu\n" ,
                          sizeof (struct  couleur3 ));
			
            
                Remarque:  L'affichage de ce programme: 7
            
            
                 
         
        
     
    
        
        
            
                          struct  couleur4{ //alignement de 4 octets
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
                           unsigned char  _pad;
			   unsigned int   count;
                        };
                          struct  couleur5{ //alignement de 4 octets
                           unsigned char  rouge;
                           unsigned char  _pad1[3];
			   unsigned int   count;
                           unsigned char  vert;
                           unsigned char  bleu;
                           unsigned char  _pad2[2];
                        };
			
            
                Remarque:  Utilisez l'option  gcc -Wpadded   pour savoir si une structure nécessite du padding our être alignée
            
            
         
        
     
    
        
        
            
                          struct  couleur{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
                        };
                          int  main () {
                           struct  couleur c1 ;
                           struct  couleur *scptr  = &c1 ;
                           c1.bleu  = 0xff ;
                           scptr->bleu  = 0x01 ;
                           printf (
                          "c1.bleu: %hhx\n" , c1.bleu ); //0x01
                           (*scptr).bleu  = 0x22 ;
                           printf (
                          "c1.bleu: %hhx\n" , c1.bleu ); //0x22
                        }
			
            
                Source: https://commons.wikimedia.org/wiki/File:AdditiveColorMixiing.svg 
             
         
        
     
    
        
        
            
                
                           struct  couleur *scptr  = &c1 ;
	            
            
            Les notations équivalents 
            
                
                    (*scptr).bleu 
                    scptr->bleu 
                 
            
         
        
     
    
        
        
            
                          struct  couleur{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
                        };
                          void  change (
                          struct  couleur *c) {
                           c->bleu  = 0x01 ;
                        }
                          int  main () {
                           struct  couleur c1 ;
                           c1.bleu  = 0xff ;
                           change(&c1 );
                           printf (
                          "c1.bleu: %hhx\n" , c1.bleu ); //0x01
                        }
			
        
        
     
    
        
        
            
                          struct  couleur{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
                        };
                          void  nochange (
                          struct  couleur c) {
                           c.bleu  = 0x03 ;
                        }
                          int  main () {
                           struct  couleur c1 ;
                           c1.bleu  = 0xff ;
                           nochange(c1 );
                           printf (
                          "c1.bleu: %hhx\n" , c1.bleu ); //0xff
                        }
			
        
        
     
    
        
        
            Une liste de couleurs simplement chaînée 
            
                 
         
        
     
    
        
        
            Une liste de couleurs simplement chaînée 
            
                          struct  couleur{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
			   struct  couleur *next;
                        };
			
            
                 
         
        
     
    
        
        
            Une liste de couleurs simplement chaînée 
            
                          int  main () {
                           struct  couleur first , c1 , c2 ;
                           struct  couleur *cptr ;
                           first.next  = &c1 ;
                           c1.next  = &c2 ;
                           c2.next  = NULL ;
                           cptr  = &first ;
                           while (cptr  != NULL ) { //navigation
                            printf (
                          "cptr->bleu: %hhx\n" , cptr->bleu );
                            cptr  = cptr->next ; //couleur suivante
                           }
                        }
			
            
                 
         
        
     
    
        
        
            Une liste d'entiers simplement chaînée 
            
                 
         
        
     
    
        
        
            
Une liste d'entiers simplement chaînée 
            
                          struct  element{ 
			   unsigned int   numero;
			   struct  element *suivant;
                        };
                        // insertion d'un élement dans une listevoid  insertion (struct  element *, int );
                        // parcours de la listevoid  parcours (struct  element *);
			
        
        
     
    
        
        
            
La saisie d'entiers par l'utilisateur 
            
                          int  main () {
                           struct  element premier ;
                           premier.suivant  = NULL ;
                           while (1) {
                             int  num ;
                             char  strnum [50];
                             fgets (strnum , sizeof(strnum ), stdin );
                             if (strcmp (strnum , "FIN\n" ) == 0) {
                               break ;
                             }
                             sscanf (strnum , "%d\n" , &num );
                             insertion (&premier , num );
                           }
                           parcours (&premier );
                        }
			
        
        
     
    
        
        
            Une liste d'entiers simplement chaînée: insertion 
            
                 
         
        
     
    
        
        
            Insertion d'un élément dans une liste simplement chaînée 
            
                          void  insertion (struct  element *premier , int  num ) {
                            struct  element *nouveau ;
                            nouveau  = malloc (sizeof (*nouveau ));
                            nouveau->num  = num; 
                            nouveau->suivant  = premier->suivant ;
                            premier->suivant  = nouveau ;
                          }
                           
			
            
                 
         
        
     
    
        
        
            Une liste d'entiers simplement chaînée: parcours 
            
                 
         
        
     
    
        
        
            Parcours d'une liste simplement chaînée 
            
                          void  parcours (struct  element *premier ) {
                             struct  element *elem  = premier ;
                             while (elem  != NULL ) {
                             printf("%d\n" , elem->num );
                             elem  = elem->suivant ;
                            }
                           }
			 
            
                 
         
        
     
    
        
        
            Une liste de couleurs doublement chaînée 
            
                 
         
        
     
    
        
        
            
Une liste de couleurs doublement chaînée 
            
                          struct  couleur{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
			   struct  couleur *next;
			   struct  couleur *prev;
                        };
			
        
        
     
    
        
        
            
                          int  main () {
                           struct  couleur first , c1 , c2 , last ;
                           struct  couleur *cptr  = &last ;
                           first.next  = &c1 ;
                           first.prev  = NULL ;
                           last.next  = NULL ;
                           last.prev  = &c2 ;
                           c1.next  = &c2 ;
                           c1.prev  = &first ;
                           c2.next  = &last ;
                           c2.prev  = &c1 ;
                           while (cptr  != &first ) { //navigation
                            printf (
                          "cptr->bleu: %hhx\n" , cptr->bleu );
                            cptr  = cptr->prev ; //couleur précédente
                           }
                        }
			
        
        
     
    
        
        
            Une liste d'entiers simplement chaînée 
            
                 
         
        
     
    
        
        
            
Insertion d'un élément et parcours d une liste doublement chaînée 
            
                           struct  element  {
                             int  num ;
                             struct  element *suivant ;
                             struct  element *precedent ;
                           };
                           
                           struct  liste  {
                             struct  element premier ;
                             struct  element dernier ;
                           };
                           
                           void  insertion_debut (struct  liste  *, struct  element  *);
                           void  insertion_fin (struct  liste  *, struct  element  *);
                           void  parcourir_debut (struct  liste  *);
                           void  parcourir_fin (struct  liste  *);
			
        
        
     
    
        
        
            Une liste de couleurs doublement chaînée: insertion 
            
                 
         
        
     
    
        
        
            Une liste d'entiers doublement chaînée 
            
				 void  insertion_debut (struct  liste *liste , 
			     struct  element *nouveau ) {
                             nouveau->suivant  = liste->premier.suivan t;
                             nouveau->precedent  = &liste->premier ;
                             liste->premier.suivant->precedent  = nouveau ;
                             liste->premier.suivant  = nouveau ;
                           }
                           
			
            
                 
         
        
     
    
        
        
            Une liste de couleurs doublement chaînée: insertion 
            
                 
         
        
     
    
        
        
            Une liste d'entiers doublement chaînée 
            
				 void  insertion_fin (struct  liste *liste , 
				      struct  element *nouveau ) {
                             nouveau->suivant  = &liste->dernier ;
                             nouveau->precedent  = liste->dernier.precedent ;
                             liste->dernier.precedent->suivant  = nouveau ;
                             liste->dernier.precedent  = nouveau ;
                           }
			
            
                 
         
        
     
    
        
        
            Une liste d'entiers doublement chaînée 
            
                           void  parcourir_debut (struct  liste *liste ) {
                             struct  element *elem  = liste->premier.suivant ;
                             while (elem  != &liste->dernier ) {
                                printf ("%d\n" , elem->num );
                                elem  = elem->suivant ;
                             }
                           }
                           
			
            
                 
         
        
     
    
        
        
            Une liste d'entiers doublement chaînée 
            
                           
                           void  parcourir_fin (struct  liste *liste ) {
                             struct  element *elem  = liste->dernier.precedent ;
                             while (elem  != &liste->premier ) {
                                printf ("%d\n" , elem->num );
                                elem  = elem->precedent ;
                             }
                           }
			
            
                 
         
        
     
    
        
        
            
La saisie d'entiers par l'utilisateur 
            
                           int  main () {
                             struct  liste liste ;
                             liste.premier.suivant  = &liste.dernier ;
                             liste.dernier.precedent  = &liste.premier ;
                             liste.premier.precedent  = NULL ;
                             liste.dernier.suivant  = NULL ;
                           
			
        
        
     
    
        
        
            
La saisie d'entiers par l'utilisateur 
            
                             while  (1) {
                                char  strnum [50];
                                struct  element *elem  = malloc (sizeof (*elem ));
                                fgets (strnum , sizeof (strnum ), stdin );
                                if (strcmp(strnum, "FIN\n" ) == 0) {
                                   break ;
                                }
                           
                                sscanf (strnum , "%d\n" , &elem->num );
                                insertion_fin (&liste, elem );
                             }
                           
                             parcourir_debut (&liste );
                             parcourir_fin (&liste );
                           }
			
        
        
     
    
        
        
            
                        int 
                        add(
                        int 
                        a ,
                        int 
                        b 
                        ) { 
                         return 
                        a 
                        + b ;
                        }
                        int 
                        subtract(
                        int 
                        a ,
                        int 
                        b 
                        ) { 
                         return 
                        a 
                        - b ;
                        }
                        
        
        
     
    
        
        
            
                          int  main () {
                           int  (*func )(int , int ); //pointeur de function
                           char  op  = '-' ;
                           int  num1  = 20 , num2  = 30 ;
                           if  (op  == '+' ) {
                            func  = add ;
   }
                           else  {
                            func  = subtract ;
                           }
                           printf ("value: %d\n" ,func (20, 30));
                          }
                        
        
        
     
    
        
        
            
				/* Fichier: stats.c #include 
                                        <stdio.h>  // en-têtes(headers) #include 
                                        <sys/types.h>   #include 
                                        <sys/stat.h>   #include 
                                        <unistd.h>   int  main (int  argc , char **  argv)
				{ 
                                      struct stat   sf ;
                                      stat  ("./stats.c" , &sf);
                                      printf ("Taille: %ld octets" , sf.st_size );
                                      return  0;
        
        
     
    
        
        
            
					#include 
                                        <stdio.h>  // en-têtes(headers) #include 
                                        <sys/types.h>   #include 
                                        <sys/stat.h>   #include 
                                        <unistd.h>   #include 
                                        <stdlib.h>   int  main (int  argc , char **  argv)
				{ 
                                      struct stat   sf ;
                                      int   status ;
                                      status  = stat  (argv[1] , &sf);
                                      if  (status  == -1) {
                                       perror ("Stats" );
                                       return (EXIT_FAILURE);
                                      }
                                      printf ("Taille: %ld octets" , sf.st_size );
                                      return  0;
        
        
     
    
        
        
            
La compilation  
            
				$ gcc -o stats  stats.c
			
            L'exécution 
            
				$./stats stats.c
                                Taille: ... octets
				$ echo $? 
                                0
			
        
        
     
    
        
        
            
La compilation  
            
				$ gcc -o stats  stats.c
			
            L'exécution 
            
                        $ ./stats nostats 
                        Stats: No such file or directory
                        $ echo $?
                        1
			
        
        
     
    
        
        
            
                    #include  <sys/types.h>
                    #include  <dirent.h>
                    #include  <unistd.h>
                    #include  <stdlib.h>
                    #include  <stdio.h>
                    
                    int  main (int  argc , char  **argv ) {
                       if  (argc  < 2) {
                        printf ("Usage: readdir path\n" );
                        return (EXIT_FAILURE);
                       }
                    
                       DIR  *dirp  = opendir (argv [1]);
                    
                       if  (dirp  == NULL ) {
                        perror ("opendir" );
                        return (EXIT_FAILURE);
                       }
                    
                
        
        
     
    
        
        
            
                       struct  dirent * ent;
                       while (1) {
                        ent  = readdir (dirp );
                        if  (ent  == NULL ) {
                         break ;
                        }
                        printf ("%s\n" , ent->d_name );
                       }
                    
                       closedir (dirp );
                     
                       return (0);
                    }
                
        
        
     
    
    
        
        
            Client 
            
                 
         
        
     
    
        
        
            
Client 
            
                    #define  PORT 8089
                    int  main() {
                     int  socketfd;
                     int  bind_status;
                     struct  sockaddr_in server_addr, client_addr;
                    
                     /*
                      * Création d'un socket
                      * AF_INET: Protocoles Internet IPv4
                      * SOCK_STREAM: flux d'octets bidirectionnels, basés sur la connexion
                      */ 
                     socketfd = socket(AF_INET, SOCK_STREAM, 0);
                     if  ( socketfd < 0 ) {
                      perror("Impossible d'ouvrir un socket" );
                      return  -1;
                     }
                  
        
        
     
    
        
        
            
Client 
            
                       // détails de l'adresse du serveur 
                       memset(&server_addr, 0, sizeof(server_addr));
                       server_addr.sin_family = AF_INET;
                       server_addr.sin_port = htons(PORT);
                       server_addr.sin_addr.s_addr = INADDR_ANY;
                    
                       //Se connecter au serveur 
                       int  connect_status = connect(socketfd, (struct sockaddr *) 
                           &server_addr, sizeof(server_addr));
                       if  ( connect_status < 0 ) {
                          perror("Impossible de se connecter au serveur" );
                          return  -1;
                       }
                   
        
        
     
    
        
        
            Serveur 
            
                 
         
        
     
    
        
        
            
Serveur 
            
                    int  main() {
                    
                     int  socketfd;
                     int  bind_status;
                    
                     struct  sockaddr_in server_addr, client_addr;
                    
                     /*
                      * Création d'un socket
                      * AF_INET: Protocoles Internet IPv4
                      * SOCK_STREAM: flux d'octets bidirectionnels, basés sur la connexion
                      */ 
                     socketfd = socket(AF_INET, SOCK_STREAM, 0);
                     if  ( socketfd < 0 ) {
                      perror("Impossible d'ouvrir un socket" );
                      return  -1;
                     }
                    
                   
        
        
     
    
        
        
            
Serveur 
            
                       int  option = 1;
                       setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, 
                        &option, sizeof(option));
                    
                       // détails de l'adresse du serveur 
                       memset(&server_addr, 0, sizeof(server_addr));
                       server_addr.sin_family = AF_INET;
                       server_addr.sin_port = htons(PORT);
                       server_addr.sin_addr.s_addr = INADDR_ANY;
                    
                       bind_status = bind(socketfd, (struct sockaddr *) 
                         &server_addr, sizeof(server_addr));
                       if  (bind_status < 0 ) {
                        perror("Impossible de se lier à un socket" );
                        return  -1;
                       }
                    
                       // Commencez à écouter le socket 
                       listen(socketfd, 10);
                   
        
        
     
    
        
        
            
                       char  data[1024];
                    
                       int  client_addr_len = sizeof(client_addr);
                       int  client_socket_fd = accept(socketfd, 
                         (struct sockaddr *) &client_addr, &client_addr_len);
                       if (client_socket_fd < 0 ) {
                        perror("Impossible d'accepter les demandes des clients" );
                        return  -1;
                       }
                   
        
        
     
    
        
        
            6 étapes de la chaine de compilation 
            
                 
         
        
     
    
        
        
            
1. Préprocesseur 
            cercle.c 
            #ifndef  PI
			#define  PI 3.14159
			#endif 
			float  area (
			float  radius ) { return (PI * radius 
						* radius ); 
    
        
        
            
1. Préprocesseur 
            
                  $ gcc -E cercle.c
		  # 1 "cercle.c"
# 1 ""
# 1 ""
# 31 ""
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "" 2
# 1 "cercle.c"
float area(float radius) {
  return(3.14 * radius * radius);
}
                      
        
        
     
    
        
        
            
2. Langage intermédiaire 
            
                  $ gcc -v bonjour.c # les étapes importantes
                  $ gcc -save-temps -v bonjour.c # les fichiers *.i, *.s
                  $ gcc -fdump-tree-all bonjour.c
                  $ gcc -fdump-rtl-all bonjour.c
                  
        
        
     
    
        
        
            
2. Langage intermédiaire 
            
                  $ gcc -fdump-tree-all -c cercle.c
		  $ cat cercle.c.005t.gimple
area (float radius)
{
  float D.1914;
  _1 = (double) radius;
  _2 = _1 * 3.140000000000000124344978758017532527446746826171875e+0;
  _3 = (double) radius;
  _4 = _2 * _3;
  D.1914 = (float) _4;
  return D.1914;
}
                  
        
        
     
    
        
        
            3. Optimisation de code 
            
                  $ gcc -O2 bonjour.c
                  $ gcc -O3 bonjour.c
                  
            
                Remarque:  Autres optimisations: -O1 -O2 -O3 -Os -Ofast -Og
            
            
         
        
     
    
        
        
            
4. Génération de code natif 
            
                  $ gcc -S bonjour.c
                  $ cat bonjour.s
                  
        
        
     
    
        
        
            
4. Génération de code natif et l'optimisation de code 
            
                  int  main () {
                    int  num  = 2 + 3;
                    return (0);
                  }
                  
            Compilation (Pas d'optimisations) 
            
                  $ gcc -O0 -S add.c
                  
            
                  add.s 
                    main:
                    .LFB0:
                      .cfi_startproc
                      pushq   %rbp
                      .cfi_def_cfa_offset 16
                      .cfi_offset 6, -16
                      movq    %rsp, %rbp
                      .cfi_def_cfa_register 6
                      movl    $5, -4(%rbp)
                      movl    $0, %eax
                      popq    %rbp
                      .cfi_def_cfa 7, 8
                      ret
                      .cfi_endproc
                  
        
        
     
    
        
        
            
4. Génération de code natif et l'optimisation de code 
            
                  int  main () {
                    int  num  = 2 + 3;
                    return (0);
                  }
                  
            Compilation (optimisation: 2) 
            
                  $ gcc -O2 -S add.c
                  
            
                  add.s 
                    main:
                    .LFB0:
                      .cfi_startproc
                      xorl    %eax, %eax
                      ret
                      .cfi_endproc
                  
        
        
     
    
        
        
            
4. Génération de code 
            sur une machine d'architecture 64 bits 
            
                  $ gcc bonjour.c
                  $ file a.out 
                   a.out: ELF 64-bit LSB shared object, x86-64
                  
        
        
     
    
        
        
            
4. Génération de code 
            sur une machine d'architecture 64 bits 
            
                  $ gcc -march=i686 -m32 bonjour.c
                  $ gcc -S -march=i686 -m32 bonjour.c
                  $ file ./a.out 
                   ./a.out: ELF 32-bit LSB shared object, Intel 80386
                  
        
        
     
    
        
        
            
5. Code objet 
            
                $ gcc -c client.c 
                $ gcc -c color.c 
                $ gcc -o color color.o client.o 
                
        
        
     
    
        
        
            
5. Code objet (Modifications et recompilation) 
            
                $ gcc -c client.c 
                $ gcc -c color.c 
                $ gcc -o client client.o color.o 
                $ vim client.c  # Modification du fichier  
                $ gcc -c client.c 
                $ gcc -c client.o color.o 
                $ vim client.c  # Modification du fichier  
                $ gcc -c client.c 
                $ gcc -o client client.o color.o 
                
        
        
     
    
        
        
            Makefile 
            Makefile et make permettent de créer facilement un exécutable à partir du code source. Il prend en considération la dernière heure de modification des fichiers pour décider de l'exécution ou non d'une ou plusieurs commandes.
            
                    $ cat Makefile 
                    client : client.c color.c # création de l'exécutable client 
		    <TAB> gcc -o client client.c color.c 
                
         
        
     
    
        
        
            
Makefile 
            
                    $ make
		    gcc -o client client.c color.c 
                
        
        
     
    
        
        
            
Makefile 
            
                    $ cat Makefile 
                    client : client.o color.o # création de l'exécutable client 
		     gcc -o client client.o color.o 
                    client.o : client.c client.h # compilation 
		     gcc -c client.c
                    color.o : color.c color.h # compilation 
		     gcc -c color.c
                
        
        
     
    
        
        
            
Makefile 
            
                    $ cat Makefile 
                    CC  ?= gcc
                    
                    CFLAGS  ?= -Wall -Wextra -g
                    
                    COBJS  ?= client.o color.o
                    SOBJS  ?= server.o color.o
                    
                    .SUFFIXES : .c .o
                    
                    SERVER  = server
                    CLIENT  = client
                
        
        
     
    
        
        
            
Makefile 
            
                    all : $(SERVER) $(CLIENT) #création des exécutables 
                    
                    $(SERVER ): $(SOBJS) # création de l'exécutable server 
                        $(CC) -o $(SERVER) $(SOBJS)
                    
                    $(CLIENT ): $(COBJS) # création de l'exécutable client 
                        $(CC) -o $(CLIENT) $(COBJS)
                    
                    .c.o:  # Compilation de tous les fichiers 
                        $(CC) -c $*.c
                
        
        
     
    
        
        
            
Exécution d'un Makefile 
            
                $ vim server.c # Modification du fichier   
                $ vim client.c  # Modification du fichier  
                $ vim color.c  # Modification du fichier  
                $ make # Compilation de tous les fichiers et création d'un exécutable. 
                $ vim color.c  # Modification du fichier  
                $ make # Compilation d'un seul fichier (color.c) et création d'un exécutable. 
                $ make # Ni compilation ni création d'un nouveau exécutable car aucun fichier n'a été modifié 
                
        
        
     
    
        
        
            Références 
            
            Crédits d'images