GEF 243B Programmation informatique appliquée Pointeurs aux fonctions, allocation dynamique de la mémoire et tableaux de pointeurs §10.4 – 10.5 , Apx I
Revue Répondez dans quelle région de mémoire du programme sont chacune des lignes suivantes: Code, pile, données ou tas: //A program int i = 0; //où? void main (void) { int j = 0; // où? j++; // où? } int Fctn () static int k = 0; // où? int l = 0; // où? l = l + 5; // où? JGA Beaulieu
Synopsis Pointeurs aux fonctions Allocation dynamique de la mémoire malloc() calloc() free() Tableaux de pointeurs JGA Beaulieu
Pointeurs aux fonctions Les fonctions occupent de l’espace de mémoire tout comme les autres entités de code tel que les variables, tableaux, structures… Le nom d’une fonction est un pointeur constant similaire au nom d’un tableau Il est donc possible d’avoir des variables pointeurs qui peuvent pointer à des fonctions Tout comme il est possible d’avoir des variables pointeurs qui pointent aux tableaux Make them remember what an array name refers to. It is an address that is does not change during the execution of a program. JGA Beaulieu
Pointeurs aux fonctions La syntaxe pour la déclaration d’un pointeur à une fonction est différente des autres types de pointeurs On se souvient qu’une variable de pointeur est déclaré avec le type du pointeur, l’étoile * et le nom de la variable pointeur : int* pInt; //un pointeur à un int char* pChar; //un pointeur à un char JGA Beaulieu
Pointeurs aux fonctions La syntaxe de déclaration pour un pointeur à une fonction est similaire à une déclaration de prototype Elle commence avec le type de la fonction (ce que la fonction retourne), Le nom de la variable pointeur à une fonction entre parenthèse (par convention on utilise fp pour commencer le nom) et, Les types des paramètres entre parenthèses: int (*fpInts) (int, int); void (*fpConverti) (char); char* (*fpString) (char* ,char*); Coding standard: Make them notice the function pointer prefix - fp used for pointer to function variables. The first fp fpInts points to a function returning an int and taking two ints as parameters. The second example does not return anything, and takes a char as parameter. It is important that they understand that the brackets are important. Because if the brackets are not around the pointer to function, it would be the same as a function returning a pointer type. JGA Beaulieu
Pointeurs aux fonctions Une des utilisations principales des pointeurs aux fonctions est de passer le nom d’une fonction (son adresse) à un gestionnaire de tâches Le pointeur à une fonction est donc utilisé pour démarrer des tâches dans certains systèmes Une des raisons principales pour utiliser des pointeurs aux fonctions est que le nom d’une fonction tâche peut ne pas être connu avant le temps d’exécution La flexibilité que nous donne les pointeurs aux fonctions est donc un élément clé pour concevoir des systèmes dynamiques Tell them to note the difference between the use of the name function and task. Without going into too many details, tell them that a single function can be stated many times in different tasks. So the same function could be executed N times in parallel. I do not think that we should go into threads in this course. A dynamic system does not have a known set of tasks at startup the tasks are created as we go (we know our functions, but the tasks may change from execution to execution). Unlike our traditional definition of a programs a dynamic system grows to meet certain conditions either in the environment or as a result of a state change in the program. JGA Beaulieu
On peut passer un pointeur à une fonction comme paramètre à une autre fonction: #include <stdio.h> void ExecUnit(void (*fp) (int, int), int, int); void Difference (int a, int b); void main(void) { ExecUnit(Difference, 5,4); getchar(); } void Difference (int a, int b) printf("Difference is: %d", a-b); return; void ExecUnit(void (*fp) (int, int), int c, int d) (*fp)(c,d); Here we have a prototype for the function ExecUnit that will take as parameter a pointer to an int function that takes two ints as parameters) also ExecUnit takes two ints We then have a prototype of a function Difference that returns nothing and take two ints. In main, we pass the address of the function Difference to the ExecUnit. Explain to them that ExecUnit is expecting a pointer to a function that is void and takes two ints as parameters. Here we pass the name of such a function. Show them in ExecUnit how the function is called through a pointer and the passing of two parameters (here two ints) Code as executed #include <stdio.h> void ExecUnit(void (*fp) (int, int),int,int); void Difference (int a, int b); void main(void) { ExecUnit(Difference,5,6); getchar(); } void Difference (int a, int b) printf("Difference is: %d", a-b); return; void ExecUnit(void (*fp) (int, int), int c, int d) (*fp)(c,d);
Allocation dynamique de la mémoire Demander plus de mémoire… Et l’obtenir. JGA Beaulieu
Allocation dynamique de la mémoire SVP monsieur, j’en veux plus Picture of Richard Charles as Oliver Twist JGA Beaulieu
Allocation dynamique de la mémoire Nous avons vue un exemple de malloc quand nous avons appris les pointeurs à void La fonction malloc retourne un bloc de mémoire qui contient le nombre d’octets spécifié par son paramètre. La fonction retourne un pointeur à void pour le premier octet du bloc de mémoire nouvellement alloué La mémoire allouée contient des déchets JGA Beaulieu
Allocation dynamique de la mémoire Le prototype de malloc (tel que définit dans le langage) est montré ici: void* malloc (size_t size); Le typedef size_t est définit dans plusieurs fichiers entête incluant stdio.h et mem.h Il est habituel d’utiliser l’opérateur sizeof() quand on demande de la mémoire: int* pInt = NULL; pInt = (int *)malloc (sizeof(int)); size_t is normally an unsigned int and is large enough to provide the maximum amount of memory in a computer. Forouzan p 489 Make them notice the casting operator in front of the malloc function call because the pointer returned by the malloc function is void. Draw pointer to null and point to block without label. JGA Beaulieu
Allocation dynamique de la mémoire Un appel à malloc demande de la mémoire sur le tas. Si il n’y a pas assez de mémoire sur le tas du programme, vous avez une condition qui s’appelle débordement C’est la responsabilité du programmeur de s’assurer qu’un débordement ne se produit pas, ou de résoudre le problème si cela se produit pInt = (int *)malloc (sizeof(int)) if (pInt == NULL) exit(1); //Pas de mémoire disponible Si on laisse un débordement se produire sans le traiter, on peut obtenir des résultats invalides ou un crash. You also cannot call malloc with a zero size. Usually NULL pointer or application dependant result. JGA Beaulieu
Allocation dynamique de la mémoire calloc est une autre façon de demander de la mémoire. Cette fonction est surtout utilisée pour les tableaux. calloc diffère de malloc de deux façons principales: Elle alloue un bloc contiguë de mémoire capable de contenir tout le tableau. Elle demande que l’on connaisse le nombre des éléments dans le tableau et la grosseur des éléments calloc claire toute la mémoire avec des zéros JGA Beaulieu
Allocation dynamique de la mémoire Vous utilisez calloc comme suit: int* pInt = NULL; if (!pInt = (int*)calloc (200,sizeof(int)))) exit(1); //pas de mémoire sort Cet appel donne de la mémoire pour un tableau de 200 éléments de type int JGA Beaulieu
Allocation dynamique de la mémoire Vous devriez toujours relâcher la mémoire quand vous en avez plus besoin Pour ce faire vous utilisez la fonction free pour relâcher la mémoire dynamique free(pInt);//relâche le bloc de //mémoire pointé par pInt JGA Beaulieu
Allocation dynamique de la mémoire Quand vous utilisez la fonction free, c’est le bloc de mémoire à qui l’on pointe qui est relâché. La variable pointeur existe encore. Le pointeur contient l’adresse du bloc de mémoire même après le free!!! Une erreur commune est d’utiliser un pointeur à un bloc de mémoire après un free. C’est une bonne pratique que de mettre le pointeur à NULL immédiatement après un appel à free JGA Beaulieu
Tableaux de pointeurs Une des structures les plus utiles que nous pouvons construire avec la mémoire dynamique est un tableau de pointeurs Ce genre de structure est utile quand le nombre d’éléments varie de rangée en rangée dans le tableau. Nous pourrions utiliser un tableau de grandeur fixe (2-D) avec la dimension maximum qui est égale à la plus grande rangée, mais cela serait une perte d’espace An array of pointers is also called a ragged array Forouzan p. 492 JGA Beaulieu
Tableaux de pointeurs Vous déclarez un tableau de pointeurs comme suit: int** table; Après la déclaration, vous demandez de la mémoire pour chaque rangée dans le tableau à 2-D. La prochaine diapo provient de votre livre de C Forouzan edition 2 (p.492) JGA Beaulieu
Figure 10-20 from Forouzan.
Quiz Time Quelle est la syntaxe pour déclarer un pointeur à une fonction? Où est-ce que la mémoire est allouée pour les fonctions malloc et calloc? type (*ptr) (parameters types); Heap. Finally mention to them that there is also a realloc to change the size of the allocated memory. But this function is not efficient at all and should be used sparingly. JGA Beaulieu