Programmation en C Les pointeurs, les structures et les fonctions
John Samuel
                          CPE Lyon
                        Année: 2017-2018
                        Courriel: john(dot)samuel(at)cpe(dot)fr
                        
Une architecture n-bit peut adresser une mémoire de taille 2n.
 
                        La capacité de la mémoire vive d'un ordinateur est de 4GO, 8GO, 16GO etc.
 
                        est l'ordre dans lequel les octets sont organisés en mémoire.
Remarque: On va utiliser petit-boutiste dans notre cours
	            
		      char c = 'a';
	              char *my_char_addr = &c;
		    
                   
		     Remarque: my_char_addr = 0xab71
                   
	            
		      short s = 0xa478;
	              short *my_short_addr = &s;
		    
                   
		     Remarque: my_short_addr = 0xab71
                   
	            
		      int i = 0xa47865ff;
	              int *my_int_addr = &i;
		    
                   
		     Remarque: my_int_addr = 0xab71
                   
	            
		      long int li = 0xa47865ff;
	              long int *my_long_int_addr = &li;
		    
                   
		     Remarque: my_long_int_addr = 0xab71
                   
float (32-bit)
Remarque: IEEE 754
double (64-bit)
Remarque: IEEE 754
	            
		      float f = 2;
	              float *my_float_addr = &f;
		    
                   
		     Remarque: my_float_addr = 0xab71
                   
	            
		      float f = 1;
	              float *my_float_addr = &f;
		    
                   
		     Remarque: my_float_addr = 0xab71
                   
	            
		      double d = 2;
	              double *my_double_addr = &d;
		    
                   
		     Remarque: my_double_addr = 0xab71
                   
	            
		      double d = 2;
	              double *my_double_addr = &d;
		    
                   
		     Remarque: my_double_addr = 0xab71
                   
| Type | Code de conversion | 
|---|---|
| pointeur | %p | 
                              
   printf("char : %p\n", my_char_addr);
                              
   printf("short : %p\n", my_short_addr);
                              
   printf("int : %p\n", my_int_addr);
                              
   printf("long int : %p\n", my_long_int_addr);
                              
   printf("float : %p\n", my_float_addr);
                              
   printf("double : %p\n", my_double_addr);
                          
		L'opérateur de déréférenciation * désigne l'objet pointé par un pointeur
		      char
                      c 
                        = 'a';
	              char
                       *my_char_addr
                        = &c;
                      printf 
                        ("%c",
                         *my_char_addr);
                         
                      
		    
		L'opérateur * est utilisé pour manipuler un objet pointé
		      char
                      c 
                        = 'a';
	              char
                       *my_char_addr
                        = &c;
                      c 
                        = 'b';
                       *my_char_addr
                        = 'c';
                      printf 
                        ("%c",
                         c);
                         
		    
                    
                      c
		    
	            
                      //le caractère 
                        pointé par my_char_addr prend la valeur 'c'
		    
		L'opérateur * est utilisé pour manipuler un objet pointé
		      int
                      i 
                        = 0x20;
	              int
                       *my_int_addr
                        = &i;
                       *my_int_addr
                        = 1;
                       *my_int_addr
                        = *my_int_addr
                        + 1;
                      //i = 0x2
                      
                       i
                        = i
                        + 3;
                      //i = 0x5
                      
                      printf 
                        ("%x",
                         *my_int_addr);
                         
		    
                    
                      5
		    
		Un tableau est un ensemble d'éléments homogènes.
		      char
                      a[8] 
                        = {0xff,0x65,0x78,
                            0xa4,0x0,0x0,0x0,0x0};
	              char
                       *ptr
                        = &a[0];
	            
                   
		      char
                      a[8] 
                        = {0xff,0x65,0x78,
                            0xa4,0x0,0x0,0x0,0x0};
	              char
                       *ptr
                        = &a[0];
                       ptr
                        = ptr + 1;
	            
                   
		      short
                      s[4] 
                        = {0x65ff,0xa478}
	              short
                       *sptr
                        = &s[0];
	            
                   
		      short
                      s[4] 
                        = {0x65ff,0xa478}
	              short
                       *sptr
                        = &s[0];
                       sptr
                        = sptr + 1;
	            
                   
		     Remarque: Notez-bien la position de sptr.
                   
Imaginez les trois variables suivantes:
                     
	              int
                      *iptr,
	              float
                      *fptr,
	              double
                      *dptr
                     . Elles ont toutes la même valeur (0x4).
                     
                     
                      iptr = 
                      iptr + 2;
	              fptr =
                      fptr + 2;
	              dptr = 
                      dptr + 2;
                     
                     
Donnez les valeurs de iptr, fptr, dptr.
	            
		      short
                      s[4] 
                        = {0x65ff,0xa478}
	              short
                       *sptr
                        = &s[0];
	            
                   
	            
	              short
                       *sptr
                        = s;
	            
                   
	            
		      short
                      s[4] 
                        = {0x65ff,0xa478}
	              short
                       *sptr
                        = s;
	            
                   
	            
                       printf(
                       "%hd",
                       *(sptr+3))
	            
                   
	            
                       printf(
                       "%hd",
                       *(s+3))
	            
                   
	            
                       printf(
                       "%hd",
                       s[3])
	             
                   
	            
                       printf(
                       "%hd",
                       sptr[3])
	             
                   
	            
		      short
                      s[2] 
                        = {0x65ff,0xa478}
	            
                   
| Notation indicielle | Notation pointeur | 
|---|---|
| &s[0] | s | 
| &s[i] | s+i | 
| s[0] | *s | 
| s[i] | *(s+i) | 
			short 
                            *sptr1,
			    *sptr2;
                
			| Opérateur | Exemple | 
|---|---|
| pointeur + entier | sptr1 + 2 | 
| pointeur - entier | sptr1 - 2 | 
| pointeur1 - pointeur2 | sptr1 - sptr2 | 
	            
		      char 
                        a 
                        = 'a';
	              char 
                        *cptr
                        = &a;
	              int 
                        i
                        = 1;
                         cptr 
                        = &i;
		    
		    
                     $ gcc ...
                   
                     warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
                     cptr = &i;
		    
	            
		      char 
                        a 
                        = 'a';
	              char 
                        *cptr
                        = &a;
	              void 
                         *vptr 
                        = &a;
	              int 
                        i
                        = 1;
                         vptr 
                        = &i;
	              float 
                        f
                        = 1;
                         vptr 
                        = &f;
		    
                   
		      short 
                        s 
                        = 0xffff;
	              int 
                        i
                        = s
		    
                        
	          	     Remarque: N'oubliez pas d'utiliser sizeof.
                   
		          short 
                          s 
                           = 0xffff;
		          float 
                          f 
                           = 30.999;
	                  int 
                          i
                           = (int) s;
	                  int 
                          j
                           = (int) f;
		    
                
	           Remarque: Une conversion explicite (typecasting): (type)
                
	            
		      char 
                        a 
                        = 'a';
		      char 
                        b 
                        = 'b';
	              char 
                        *cptr
                        = &a;
	              void 
                         *vptr 
                        = &b;
                      cptr 
                        = (char *)vptr;
		    
                   
est un ensemble d'éléments homogènes
			  char prenom[135][30];
			  char nom[135][30];
			  char rue[135][30];
			  char ville[135][30];
			  short notes[135];
			
			Question: Quelles sont les problèmes?
est un ensemble d'éléments hétérogènes.
                          struct etudiant{ 
			   char prenom[30];
			   char nom[30];
			   char rue[30];
			   char ville[30];
			   short notes;
                        };
			
		
                          struct etudiant dupont;
                          strcpy(dupont.prenom,  "Dupont");
                          strcpy(dupont.nom,  "Pierre");
                          strcpy(dupont.rue,  "Boulevard du 11 novembre 1918");
                          strcpy(dupont.ville,  "Villeurbanne");
                          dupont.notes = 19;
			
		
                          struct etudiant etudiant_cpe[135];
                          strcpy(etudiant_cpe[0].prenom,  "Dupont");
                          strcpy(etudiant_cpe[0].nom,  "Pierre");
                          strcpy(etudiant_cpe[0].rue,  "Boulevard du 11 novembre 1918");
                          strcpy(etudiant_cpe[0].ville,  "Villeurbanne");
                          etudiant_cpe[0].notes = 19;
			
		
                          struct adresse{ 
			   char rue[30];
			   char ville[30];
                          };
                          struct etudiant{ 
			   char prenom[30];
			   char nom[30];
			   struct adresse adresse;
			   short notes;
                        };
			
		
                          struct etudiant{ 
			   char prenom[30];
			   char nom[30];
                           struct adresse{ 
			    char rue[30];
			    char ville[30];
                           } adresse;
			   short notes;
                        };
			
		
                          struct etudiant etudiant_cpe[135];
                          strcpy(etudiant_cpe[0].prenom,  "Dupont");
                          strcpy(etudiant_cpe[0].nom,  "Pierre");
                          strcpy(etudiant_cpe[0].adresse.rue,  "Boulevard du 11 novembre 1918");
                          strcpy(etudiant_cpe[0].adresse.ville,  "Villeurbanne");
                          etudiant_cpe[0].notes = 19;
			
		
                          typedef struct etudiant{ 
			   char prenom[30];
			   char nom[30];
                           struct adresse{ 
			    char rue[30];
			    char ville[30];
                           } adresse;
			   short notes;
                        } etudiant;
			
                        
                        etudiant dupont;
			
		
                        typedef int integer;
                        integer i = 10;
			
		
				/* Fichier: bonjour2.c 
 * affiche un message à l'écran en utilisant un variable
				
 * auteur: John Samuel 
 * Ceci est un commentaire
				sur plusieurs lignes 
 */ 
 
 #include <stdio.h> // en-têtes(headers) 
				
 int main()
				{ 
   int year = 2017;
				//déclaration d'un variable 
   printf("Bonjour le Monde!!! C'est l'annee %d", year);
   return 0;
 }
			
		
                        int
                        add(
                        int,
                        int);
                         
			
                        int
                        add(
                        int
                        a,
                        int
                        b
                        ) { 
                         return
                        a
                        + b;
                        }
                         
		
                        int
                        add(
                        int,
                        int);
                         
			
                        int
                        add(
                        int
                        a,
                        int
                        b
                        ) { 
                         return
                        a
                        + b;
                        }
                         
		
                        type
                        fonction(
                        [type,]*);
                         
			
                        type
                        fonction(
                        [type
                         variable,]*)
                        { 
                         [return
                        valeur];
                        }
                         
                        
	           Remarque: type: void, les types de base, les types composés
                        
		        #include 
                        "operators.h" // en-têtes(headers) 
                        int
                         num1
                         = 20, 
                         num2
                         = 60; 
                        int
                         sum
                         = 
                        add(
                        num1,
                        num2);
                         
                        Remarque: Regardez l'utilisation de " " dans en-têtes
                        void
                        print(
                        char *,
                        int);
                         
			
			#include <stdio.h> // en-têtes(headers) 
                        void
                        print(
                        char *
                        name,
                        int
                        size
                        ) { 
                              int
                             i;
                              for( 
                             i = 0; 
                             i  <
                             size; 
                             i++) {
                               
                             printf(
                             "%c",
                             name[i]);
                              }
                        }
                         
                        
	                Remarque: Il n'y a pas de 
                        return
                        
				/* Fichier: bonjour3.c 
 * affiche un message à l'écran en utilisant print
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        "name.h" // en-têtes(headers) 
				 int main()
				{  
                                     print(
                                    "Bonjour le Monde!!!");
                                      char
                                     message[] =
                                     "Pierre";
                                      print("Je suis ");
                                     print(message); return 0;
 }
			
		
				$ gcc -o bonjour bonjour3.c name.c
			
			
				$./bonjour 
 Bonjour le Monde!!! Je suis Pierre
			
		
				/* Fichier: bonjour4.c 
 * affiche un message à l'écran en utilisant les arguments de la ligne de commandes.
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        "name.h" // en-têtes(headers) 
				 int main(int argc, char ** argv)
				{  
                                      print("Bonjour le Monde. Je suis ");
                                     print(argv[1]); return 0;
 }
			
		
				$ gcc -o bonjour bonjour4.c name.c
			
			
				$./bonjour John
 Bonjour le Monde. Je suis John
			
		
				/* Fichier: bonjour4.c 
 * affiche un message à l'écran en utilisant les arguments de la ligne de commandes.
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        "name.h" // en-têtes(headers) 
				 int main(int argc, char ** argv)
				{  
                                      print("Bonjour le Monde. Je suis ");
                                     if ( argc == 2 ) {  
                                      print(argv[1]); } return 0;
 }
			
                        
	                Remarque:
                        argv[0] est toujours le nom de la fichier exécutable (e.g., bonjour)
                        
				/* Fichier: addition.c 
 * affiche un message à l'écran en utilisant scanf.
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
				 int main(int argc, char ** argv)
				{  
                                      int num1, num2;
                                      printf("Tapez numéro 1");
                                      scanf("%d", &num1);
                                      printf("Tapez numéro 2");
                                      scanf("%d", &num2);
                                      printf("La somme: %d\n", num1 + num2);
                                      return 0;
 }
			
                        
	                Remarque: Regardez l'opérateur  &.
                        
				/* Fichier: addition.c 
 * affiche la somme de deux numéros saisis par l'utilisateur
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
				 int main(int argc, char ** argv)
				{  
                                      int num1, num2;
                                      printf("Tapez deux numéros: ");
                                      scanf("%d %d", &num1, &num2);
                                      printf("La somme: %d\n", num1 + num2);
                                      return 0;
 }
			
                        
	                Remarque: Regardez l'opérateur  &.
                        
				/* Fichier: bonjour5.c 
 * affiche un message à l'écran en utilisant scanf.
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
				 int main(int argc, char ** argv)
				{  
                                      char nom[50];
                                      printf("Bonjour. Votre nom?  ");
                                      scanf("%s", nom);
                                      printf("Bonjour %s!", nom);
                                      return 0;
 }
			
                        
	                Remarque: Regardez s sans l'opérateur &.
                        
| Mots clés | Code de conversion | 
|---|---|
| char | c | 
| unsigned char | hhu | 
| short | hd | 
| unsigned short | hu | 
| int | d, i | 
| unsigned int | u | 
| long int | ld | 
| unsigned long int | lu | 
| Mots clés | Code de conversion | 
|---|---|
| long long int | lld | 
| unsigned long long int | llu | 
| float | f, F | 
| double | g, G | 
| long double | Lg | 
| string of characters | s | 
                           $ man ls
                           $ man 3 scanf
                           $ man 3 printf
                           $ man 2 open
                           $ man fopen
                           ..
                        
		
                           NAME
                            scanf
                            ... 
                           SYNOPSIS
                            ... 
                           DESCRIPTION
                            ... 
                           RETURN VALUE
                            ... 
                           ..
                        
		
				/* Fichier: string.c 
 * manipulation d'une chaine de caractères.
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
					#include 
                                        <string.h>  
				 int main(int argc, char ** argv)
				{  
                                      char nom[10];
                                      printf("Bonjour. Votre nom?  ");
                                      scanf("%s", nom);
                                      printf("La taille: %lu\n", strlen(nom));
                                      return 0;
 }
			
			Remarque: strlen calcule la taille d'une chaine de caractères.
				$ gcc -o strlen string.c
			
			
				$./strlen
				Bonjour. Votre nom? John
				La taille: 4
			
			
				$./strlen
				Bonjour. Votre nom? : ABCDEFGHIJKLMNOPQRSTUVWXYZ 
                                *** stack smashing detected ***: ./strlen terminated 
			
		
				/* Fichier: string.c 
 * manipulation d'une chaine de caractères.
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
					#include 
                                        <string.h>  
				 int main(int argc, char ** argv)
				{  
                                      char nom[10];
                                      printf("Bonjour. Votre nom?  ");
                                      scanf("%9s", nom);
                                      printf("La taille: %lu\n", strnlen(nom, 10));
                                      return 0;
 }
			
			Remarque: strnlen calcule la taille d'une chaine de caractères (taille maximum).
				$ gcc -o strnlen string2.c
			
			
				$./strnlen
				Bonjour. Votre nom? John
				La taille: 4
			
		strcat concatene deux chaines de caractères strncat concatene deux chaines de caractères avec une taille maximum donnée par l'utilisateur.strcpy copie deux chaines de caractèresstrncpy copie deux chaines de caractères avec une taille maximum donnée par l'utilisateur 
                          strcmp compare deux chaines de caractèresstrncmp compare deux chaines de caractères avec une taille maximum donnée par l'utilisateur
				/* Fichier: string3.c 
 * manipulation d'une chaine de caractères.
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
					#include 
                                        <string.h>  
				 int main(int argc, char ** argv)
				{  
                                      char message[]= {"Bonjour"}, nom[]= {"John"}, string[20] = "";
                                      strncat(string, message, 19);
                                      strcat(string, " ");
                                      strncat(string, nom, 19);
                                      printf("%s", message));
                                      return 0;
 }
			
                        
				/* Fichier: string4.c 
 * manipulation d'une chaine de caractères.
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
					#include 
                                        <string.h>  
				 int main(int argc, char ** argv)
				{  
                                      char message[]= {"Bonjour"}, nom[]= {"John"}, string[20] = "";
                                      strncpy(string, message, 19);
                                      strcpy(string, " ");
                                      strncpy(string, nom, 19);
                                      printf("%s", message));
                                      return 0;
 }
			
                        
				$ gcc -o strncat string3.c
				$ gcc -o strncpy string4.c
			
			
				$./strncat
				Bonjour John
			
			
				$./strncpy
				John
			
                        
				/* Fichier: file.c 
 * manipulation d'une fichier
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
					#include 
                                        <sys/types.h>  
					#include 
                                        <sys/stat.h>  
					#include 
                                        <fcntl.h>  
					#include 
                                        <unistd.h>  
				 int main(int argc, char ** argv)
				{  
                                      char  content[1000];
                                      int  fd, count, size;
                                      fd = open ("./file.c", O_RDONLY);
                                      size = read(fd, content, 1000);
                                      for (count = 0; count < size; count ++) {
                                       printf("%c", content[count]);
                                      }
  
                                      close(fd);
                                      return 0;
 }
			
                        
				/* Fichier: file.c 
 * manipulation d'une fichier
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
					#include 
                                        <sys/types.h>  
					#include 
                                        <sys/stat.h>  
					#include 
                                        <fcntl.h>  
					#include 
                                        <unistd.h>  
				 int main(int argc, char ** argv)
				{  
                                      char  content;
                                      int  fd, count, size;
                                      fd = open ("./file.c", O_RDONLY);
                                      while (1) {
                                       size = read(fd, &content, 1);
                                       if (size < 1) {
                                        break;
                                       }
                                       printf("%c", content);
                                      }
  
                                      close(fd);
                                      return 0;
 }
			
                        
				/* Fichier: file.c 
 * manipulation d'une fichier
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
					#include 
                                        <sys/types.h>  
					#include 
                                        <sys/stat.h>  
					#include 
                                        <fcntl.h>  
					#include 
                                        <unistd.h>  
				 int main(int argc, char ** argv)
				{  
                                      char  content[] = "Bonjour";
                                      int  fd, count, size;
                                      fd = open ("./message.txt", O_CREAT|O_WRONLY);
                                      size = write(fd, &content, sizeof(content));
  
                                      close(fd);
                                      return 0;
 }
			
                        
					#include 
                                        <stdlib.h>  
                                        void * 
                                        malloc(
                                        size_t size);
                                        void * 
                                        calloc(
                                        size_t nmemb,
                                        size_t size);
                                        void 
                                        free(
                                        void * ptr); // désallocation ou libération de mémoire
 
			
		
				/* Fichier: memory.c 
 * Allocation dynamique de mémoire
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
					#include 
                                        <stdlib.h>  
				 int main(int argc, char ** argv)
				{  
                                      char  *content = malloc(10 * sizeof(char)); 
                                      strncat(content, "Bonjour", 10);
                                      free(content); //libération de mémoire
                                      return 0;
 }
			
		
				/* Fichier: memory.c 
 * Allocation dynamique de mémoire
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
					#include 
                                        <stdlib.h>  
				 int main(int argc, char ** argv)
				{  
                                      char  *content = calloc(10, sizeof(char)); 
                                      strncat(content, "Bonjour", 10);
                                      free(content); // libération de mémoire
                                      return 0;
 }
			
		est declarée comme une structure.
                          union etudiant{ 
			   char prenom[30];
			   char nom[30];
			   char rue[30];
			   char ville[30];
                        };
			
			Remarque: La taille d'une union est égale la taille du élément plus grand.
                          union etudiant dupont;
                          strcpy(dupont.nom,  "Dupont");
                          printf("%s", dupont.prenom);
                          printf("%s", dupont.rue);
                          printf("%s", dupont.ville);
			
			
                        Dupont
                        Dupont
                        Dupont
			
			Remarque: Tous les élements partagent la même espace de mémoire.
                          struct content{ 
			   char type[30];
                            union{ 
			    char * ccontent;
			    int * icontent;
			    float * fcontent;
                           };
                        };
			
		
				/* Fichier: memory3.c 
 * Allocation dynamique de mémoire
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
					#include 
                                        <stdlib.h>  
				 int main(int argc, char ** argv)
				{  
                                      struct  content c;
                                      strcpy(c.type, "char", 10);
                                      if (strcmp(c.type, "char") == 0) {
                                        c.ccontent = calloc(10, sizeof(char)); 
 
                                      } 
                                      else if (strcmp(c.type, "int") == 0) {
                                        c.icontent = calloc(10, sizeof(int)); 
 
                                      } 
                                      return 0;
 }
			
		
                          union point3d{ 
			   int value[3];
                            struct{ 
			    int  x;
			    int  y;
			    int  Z;
                           };
                        };
			
		
				/* Fichier: union.c 
 * la déclaration et l'utilisation d'une union
				
 * auteur: John Samuel 
  */ 
 
 #include 
                                        <stdio.h> // en-têtes(headers) 
				 int main(int argc, char ** argv)
				{  
                                      union  point3d p;
                                      p.values[0] = 0x10;
                                      p.values[1] = 0x45;
                                      p.values[2] = 0x78;
                                      printf("%x %x %x\n", p.x, p.y, p.z);
                                      return 0;
 }