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 : 2018-2019Courriel : john(dot)samuel(at)cpe(dot)fr
                        
                
                              
		 
		
	 
	
		
		
			Objectifs 
			
				Préprocesseur 
				Les appels systèmes 
				Les erreurs 
				La chaine de compilation 
			 
		 
		
	 
	
		
		
			
cercle.c 
			#define  PI 3.14159
			float  area (
			float  radius ) { return (PI * radius 
						* radius ); 
	
		
		
			Prototype (defs.h) 
                        
			#define  PI 3.14159
			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
			
		 
		
	 
	
		
		
                        
			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 
			
				#ifndef  __OPERATORS_H__ #define  __OPERATORS_H__ 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 (
			
		 
		
	 
	
		
		
			
                          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 
                         
		 
		
	 
	
		
		
                        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
                        }
			
		
		
	 
	
		
		
			
                          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 
			
                          struct  couleur{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
			   struct  couleur *next;
                        };
			
                         
		
	 
	
		
		
			Une liste de couleurs 
			
                          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 de couleurs 
			
                          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
                           }
                        }
			
                         
		
	 
	
		
		
                        
                        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);
                    }
                
		
		
	 
	
        
		
		
                   
                    #define  PORT 8089
                    int  main() {
                     int  socketfd;
                     int  bind_status;
                     struct  sockaddr_in server_addr, client_addr;
                    
                     /*
                      * Creation of a socket
                      * AF_INET: IPv4 Internet protocols
                      * SOCK_STREAM: two-way, connection-based byte streams
                      */ 
                     socketfd = socket(AF_INET, SOCK_STREAM, 0);
                     if  ( socketfd < 0 ) {
                      perror("Unable to open a socket" );
                      return  -1;
                     }
                  
                  
                    
		 
		
	 
	
		
		
                   
                       //server address details 
                       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;
                    
                       //Connect to the server 
                       int  connect_status = connect(socketfd, (struct sockaddr *) 
                           &server_addr, sizeof(server_addr));
                       if  ( connect_status < 0 ) {
                          perror("Unable to connect to server" );
                          return  -1;
                       }
                   
                  
                    
		 
		
	 
	
		
		
                   
                    int  main() {
                    
                     int  socketfd;
                     int  bind_status;
                    
                     struct  sockaddr_in server_addr, client_addr;
                    
                     /*
                      * Creation of a socket
                      * AF_INET: IPv4 Internet protocols
                      * SOCK_STREAM: two-way, connection-based byte streams
                      */ 
                     socketfd = socket(AF_INET, SOCK_STREAM, 0);
                     if  ( socketfd < 0 ) {
                      perror("Unable to open a socket" );
                      return  -1;
                     }
                    
                   
                   
                      
		 
		
	 
	
		
		
                   
                       int  option = 1;
                       setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, 
                        &option, sizeof(option));
                    
                       //server address details 
                       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("Unable to bind to socket");
                        return  -1;
                       }
                    
                       // Start listening to the 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("Unable to accept client requests");
                        return  -1;
                       }
                   
                  
                    
		 
		
	 
	
		
		
                  Préprocesseur 
                  
                  $ gcc -E bonjour.c
                  
                  
                     
		 
		
	 
	
		
		
                  Langage intermédiaire 
                  
                  $ gcc -fdump-tree-all bonjour.c
                  $ gcc -fdump-rtl-all bonjour.c
                  
                  
                    
		 
		
	 
	
		
		
                  Optimisation de code 
                  
                  $ gcc -O2 bonjour.c
                  $ gcc -O3 bonjour.c
                  
                   
		     Remarque:  Autres optimisations: -O1  -O2  -O3  -Os -Ofast -Og
			
                   
                  
                     
		 
		
	 
	
		
		
                  Génération de code natif 
                  
                  $ gcc -S bonjour.c
                  $ cat bonjour.s
                  
                  
                     
		 
		
	 
	
		
		
                  
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
                  
		
		
	 
	
		
		
                  
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
                  
		
		
	 
	
		
		
                  Génération de code 
                  
                  $ gcc -march=i686 -m32 bonjour.c
                  $ gcc -S -march=i686 -m32 bonjour.c
                  
                  
                     
		 
		
	 
	
		
		
                
Code objet 
                
                $ gcc -c client.c 
                $ gcc -c color.c 
                $ gcc -o color color.o client.o 
                
		
		
	 
	
		
		
                
Code objet (Modifications et recompilation) 
                
                $ gcc -c client.c 
                $ gcc -c color.c 
                $ gcc -o client client.o color.o 
                $ vim client.c 
                $ gcc -c client.c 
                $ gcc -c client.o color.o 
                $ vim client.c 
                $ gcc -c client.c 
                $ gcc -o client client.o color.o 
                
		
		
	 
	
		
		
                
Makefile 
                
                    CC  ?= gcc
                    
                    COBJS  ?= client.o color.o
                    SOBJS  ?= server.o color.o
                    
                    .SUFFIXES : .c .o
                    
                    SERVER  = server
                    CLIENT  = client
                
		
		
	 
	
		
		
                
Makefile 
                
                    all : $(SERVER) $(CLIENT)
                    
                    $(SERVER ): $(SOBJS)
                        $(CC) -o $(SERVER) $(SOBJS)
                    
                    $(CLIENT ): $(COBJS)
                        $(CC) -o $(CLIENT) $(COBJS)
                    
                    .c.o: 
                        $(CC) -c $*.c
                
		
		
	 
	
		
		
                
Exécution d'un Makefile 
                
                $ vim server.c 
                $ vim client.c 
                $ vim color.c 
                $ make
                $ vim color.c 
                $ make
                
		
		
	 
	
		
		
			Références 
			
			Crédits d'images