C
Pointeur de type void Définition : Un pointeur de type générique peut pointer vers n'importe quel type d'objet Déclaration void *p Déclare un pointeur générique p dont on n'a pas encore spécifié le type. Usage : ce type de pointeur se rencontre dans la déclaration des arguments d'une fonction Idée : en déclarant le pointeur vers un argument de type void, on peut utiliser plusieurs types d'arguments Utilisation de la coercition : Il est nécessaire de caster le pointeur avant de l'utiliser pour référencer une variable ou de le faire intervenir dans une opération arithmétique d'addition ou de soustraction. Il n'est pas la peine de la caster pour lui assigner une valeur (adresse), pas plus pour le comparer avec NULL.
Caster void *x x est un pointeur sur void Cas d'un entier x est un pointeur qui pointe sur un entier (int *) x Pour accéder à la variable utilisation de l'opérateur d'indirection * *(int *) x Remarque : pour un flottant remplacer int par float
Exemple Ecrire une fonction double calculant le double de la valeur qui lui est passé en argument, avec le résultat qui soit du même type. Outre la valeur elle-même on lui passe le type de la variable. Déclaration : void double(void *x, char type) CODE COMPLET /
Fonctions comme paramètres Une fonction possède une adresse en mémoire. L'adresse désigne son emplacement mémoire où ses instructions sont rangées. On peut donc manipuler l'adresse de fonction comme une adresse de variable l'adresse d'une fonction peut donc être passée comme paramètre à une fonction. Une fonction peut être appelée par l'intermédiaire d'un pointeur vers la fonction
Pointeur de fonction Définition : L'adresse d'une fonction est symbolisée par son nom (comme les tableaux). un nom de fonction comme printf est un pointeur constant vers la fonction. Syntaxe Pour ranger l'adresse d'une fonction dans un pointeur <type> (*<pointeur>) (para) Exemple void * (*fp)(); fp est un pointeur pointant vers une fonction qui retourne un pointeur vers un type void. Si function1 est une fonction alors fp=function1 affecte au pointeur fp, via leur nom, l'adresse de la fonction function1
Appels de fonctions Une fonction peut être lancée en communiquant son adresse au compilateur donnant l'adresse de la fonction indiquant un pointeur de fonction déréférencé. L'appel de la fonction nécessite la mise en parenthèses de l'expression *<pointeur> exemple int (*fp)()=printf; /*déf d'un pointeur de fonction initialisé à l'adresse de printf*/ (*fp)("Ce texte est affiché"); /*les () de (*fp) sont très importantes*/ Evocation de fonctions mathématique non pas par leur nom mais par leur adresse : Les adresses de fonctions sont rangées dans un tableau de pointeurs de fonctions void (*t[5])() = {moyenne, somme, ecart-type, carre, racine}; on définit ici un tableau t ayant 5 éléments qui sont des pointeurs vers des fonctions de type void. (*t[4]) exécute la fonction racine.
Rappel de Syntaxe int x x variable de type entier int *x x pointeur vers un entier int *x() x fonction qui retourne un pointeur vers un entier int (*x)() x pointeur vers une fonction qui renvoie un entier (*x) exécute alors la fonction x rem : les () sont indispensable la priorité des () est plus forte que l'opérateur * int (*x)[10] int (*x())[10] int*(x[10])() int(*x[10])() int (*x)[10] x est un pointeur vers des tableaux de 10 éléments de type int int (*x())[10] x est fonction retournant une valeur de type pointeur vers des tableaux de 10 elements de type int int*(x[10])() x est un tableau de fonctions retournant des pointeur vers un entier int(*x[10])() x est un tableau de dix pointeurs vers des fonctions retournant des valeurs de type int rem : les éléments d'un tableau ne sont pas des fonctions. (mais peuvent être des pointeurs vers des fonctions) la valeur de retour d'une fonction ne doit pas être une fonction ou un tableau mais un pointeur vers un tableau ou une fonction.
Pointeur vers des structures Utilisation Pour passer une structure comme argument à une fonction. Définition de la structure Déclaration d'un pointeur vers la structure Pour initialisation : Réservation de la mémoire Accès aux membres de la structure En utilisant le nom de la structure Avec un pointeur vers la structure et l'op d'indirection * Avec un pointeur vers la structure et l'op d'indirection ->
Pointeur vers des structures Utilisation Pour passer une structure comme argument à une fonction. struct part { int nb; char nom[10]; }; struct part *p_part; struct part mapart; p_part=&mapart; Accès aux membres de la structure mapart.nb = (*p_part).nb= p_part->nb= Utilisation Pour passer une structure comme argument à une fonction. Définition de la structure Déclaration d'un pointeur vers la structure Pour initialisation : Réservation de la mémoire Accès aux membres de la structure En utilisant le nom de la structure Avec un pointeur vers la structure et l'op d'indirection * Avec un pointeur vers la structure et l'op d'indirection ->
Préprocesseur #ifndef _VALEUR_H_ /* Ce qui suit est ignoré jusqu'à l'instruction #endif si le symbole _valeur_H- est déjà défini */ #define _VALEUR_H_ /* Définition préprocesseur empêchant le fichier d'être inséré plusieurs fois dans la compilation du même fichier .c : le symbole _valeur_H_ est défini lors de la première inclusion de ce fichierlors de la phase de préprocessing*/ extern float valeur_courante; /* Référence externe à une variable globale, la variable globale n'est pas déclarée, mais on dit explicitement au compilateur qu'elle est déclarée quelque part dans le programme. En l'occurrence, elle est déclarée dans le corps du module */ #endif La présence des _ rende peu probable la présence de même nom.
Préprocesseur /* Fichier valeur.c Corps de module contenant l'implémentation des fonctions de gestion de la valeur courante */ #include "valeur.h" /* implementation des fonctions déclarées dansl'en-tête de module */ float valeur_courante; /* déclaration effective de la variable globale */ float valeur_test(){} /* Fichier main.c contenant le programme principal */ void main() { /* programme principal utilisant le module valeur */ }
Paramètre de fonction Char *strcpy(char *destination, const char *source) Il est difficile de distinguer si un paramètre comme un tableau ou un pointeur est un paramètre d'entrée, ou bien d'entrée/sortie. Mot clé const (constant)
Variable static Par défaut les variables locales sont automatiques. Elles sont crées et détruites avec l'appel et la fin de la fonction. La valeur de la variables n'est pas conservée entre deux appels Si la valeur de la variable doit être connue à l'appel de la fonction, la variable doit être définie comme statique. La variable statique est initialisée au premier appel de la fonction. static int i; Une fonction d'impression doit connaître le nb de lignes deja envoyéés vars l'imprimante pour effectuer le changement de page
Traitement des erreurs Une partie des fonctions susceptibles de renvoyer une erreur revoient un entier représentant le statut d'erreur. Généralement, une valeur de retour nulle est renvoyée s'il n'y a pas eu d'erreut. Dans le cas où le code lui-même ne n'est pas renvoyé par la fonction, celle-ci modifie une variable globale qui contient le code de l'erreur nommée errno On notera que le traitement des erreur rend le code diificile à lire.