IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Prototypes, pointeurs et const


Sujet :

C

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    34
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 34
    Par défaut Prototypes, pointeurs et const
    Bonjour,

    Je code au sein d'un projet où l'on doit utiliser du C ansi. Les règles assez contraignantes nous imposent entre autres d'abuser du const dans les prototypes de fonctions pour bien signifier ce qui peut changer ou ne pas changer.

    Si j'ai bien compris la philosophie des const :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void toto(const int arg1, /* la valeur de arg1 ne sera pas modifiée */
              int * arg2, /* arg2 peut-être modifié, *arg2 aussi */
              const int * arg3, /* la valeur de *arg3 ne sera pas modifiée, celle de arg3 le pourrait */
              int * const arg4, /* la valeur de arg4 peut être modifiée, celle de *arg4 non (valeur classique de sortie) */
              const int * const arg5) /* ni arg5, ni *arg5 n'est modifié */
    {
    [...]
    }
    Là où ça se complique, c'est dans le cas des tableaux statiques et des multi-pointeurs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    typedef int vectint[3];
    typedef int matint[3][3];
     
    void toto(const matint matrice_entree,
              const vectint vecteur_entree,
              matint const matrice_sortie,  /* ne fonctionne pas */
              vectint const vecteur_sortie) /* ne fonctionne pas */
    {
    [...]
    }
     
    void toto2(char *** tableau)
    {
    [...]
    }
     
    int main(void)
    {
      matint matrice1, matrice2;
      vectint vecteur1, vecteur2;
      char *** tableaux_de_noms;
      int i, j;
     
      toto(matrice1, vecteur1, matrice2, vecteur2);
     
      [...]
      strcpy(tableaux_de_noms[i][j], "MON NOM");
      [...]
     
      toto2(tableaux_de_noms);
     
      return 0;
    }
    Là, j'aurais outre les message d'erreur du prototype de toto les messages suivants :
    + matrice1 : warning, prototypes incompatibles
    + matrice2, vecteur2 : erreurs, prototypes incompatibles.

    Bref, mes questions :
    + comment signifier la totale constance en entrée d'une matrice ou de manière générale d'un tableau statique multi-dimensionnel ?
    + comment signifier la constance d'un double pointeur, de ce qu'il pointe et de ce que pointent ce qui est pointé ? Même question pour un triple...
    + comment signifier, pour renseigner un tableau de sortie (statique défini par typedef ou dynamique multidimensionnel) que seul le contenu au bout des pointeurs peut être changé ?
    + comment signifier, pour toto2, que tout mon tableau est constant ?
    + comment, au contraire, signifier que cette fonction va remplir mon tableau, mais ne va pas modifier les pointeurs intermédiaires ?

    Question subsidiaire : est-ce bien utile ?

    Merci d'avance pour vos avis.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 146
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void toto(const int arg1, /* la valeur de arg1 ne sera pas modifiée */
              int * arg2, /* arg2 peut-être modifié, *arg2 aussi */
              const int * arg3, /* la valeur de *arg3 ne sera pas modifiée, celle de arg3 le pourrait */
              int * const arg4, /* la valeur de arg4 peut être modifiée, celle de *arg4 non (valeur classique de sortie) */
              const int * const arg5) /* ni arg5, ni *arg5 n'est modifié */
    {
    [...]
    }
    en C les paramètres sont passés par copie. Donc
    - arg1, s'il est modifié à l'intérieur de la fonction, n'aura aucune incidence sur la variable passée en paramètre : le constance est inutile
    - arg3 ne pourra pas être modifié, puisqu'il s'agira d'une copie du pointeur, qui pointe sur la même adresse; la constance indique que la valeur pointée ne sera pas modifiée, pas que le pointeur peut l'être : il ne le peut pas
    - arg4, passage par copie, cf arg3 : inutile
    - arg5, cf arg3 et arg4, le 2° const est inutile

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void toto2(const char **const*const tableau)
    afin que le tableau ne soit pas modifié
    - ni le contenu char
    - ni les pointeurs intermédiaires
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 492
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 492
    Billets dans le blog
    1
    Par défaut
    le constance est inutile
    Tu auras juste des messages d'erreur du compilateur si tu essayes de les modifier. Ca peut signaler un code "bizarre", mais les modifications n'aura effectivement aucun effet une fois fonction terminée. On avait pas mal disserté sur le sujet ici.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void toto2(const char **const*const tableau)
    Ne serait-ce pas plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void toto2(const char *const *const *tableau)
    ?

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 146
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void toto2(const char **const*const tableau)
    Ne serait-ce pas plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void toto2(const char *const *const *tableau)
    ?
    Je ne savais pas par quel bout il faut prendre les * .
    Effectivement c'est ton écriture qui est correcte. Dans le doute on pourrait mettre const aux 3, mais vu que l'un est inutile.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 492
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 492
    Billets dans le blog
    1
    Par défaut
    Ce serait mettre un 4e const qui serait inutile plutôt ? Cf ton 1er message où mettre 2 const pour une * est inutile. En extrapolant, trois * veut dire que le 4e const est inutile.


    J'ai fait le code suivant pour tester les possibilités.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
     
     
    void f(const char * const *const *pt_tableau, int lignes, int colonnes)
    {
        int s;
        char const  *const *const  tableau =  *pt_tableau;
     
        // Niveau 0
        // --> autorisé car aucun const ne s'applique a pt_tableau et n'a pas d'effet une fois sortie de f()
        pt_tableau = NULL;
     
        // Niveau 1 d'indirection
        tableau = NULL;
        *pt_tableau = NULL;
     
        // Niveau 2 d'indirection
        for(s=0;s<lignes;s++)
        {
            *(tableau+s) = malloc( sizeof(char[colonnes]) );
            strcpy( *(tableau+s), "BOUM !"); // ne devrait pas provoquer une erreur de compilation ?
        }
     
        // Niveau 3 d'indirection
        for(s=0;s<5;s++)
            *( *(tableau) + 0 ) = 'C';
    }
     
    int main(void)
    {
        short int s;
        char* *tab = malloc( sizeof(char*) * 5 );
        for(s=0;s<5;s++)
        {
            *(tab+s) = malloc( sizeof(char[10]) );
            sprintf( *(tab+s), "chaine %d", s );
        }
     
        // Afficher
        for(s=0;s<5;s++)
            printf("%s\n", *(tab+s));
     
        f((const char *const *const *) &tab, 5, 10);
     
        // Afficher
        for(s=0;s<5;s++)
            printf("%s\n", *(tab+s));
     
        // I'm fruuuiiiit !
        for(s=0;s<5;s++)
            free( *(tab+s) );
        free(tab);
     
        return 0;
    }

    Bref, mes questions :
    Je pense que le code juste au dessus devrait t'aider à répondre à tes questions, notamment en enlevant des const dans la déclaration char const *const *const tableau = *pt_tableau; Tu devras peut-être fait des cast à l'appel des fonctions, comme je l'ai fait pour f(). Tu pourras utiliser d'autres typedef pour ces transtypages. Petit jeu de l'esprit auquel je ne vais pas me risquer de peur de me tromper que de mettre les const uniquement aux niveaux qui vont bien.

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    34
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 34
    Par défaut Prototypes, pointeurs et const
    Merci (tardif) pour vos réponses.
    Je sais que les const ne sont pas forcément utiles, mais c'est imposé, alors...

    --
    Olivier

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Prototype pointeur de fonction
    Par Kel-T dans le forum C
    Réponses: 6
    Dernier message: 26/01/2012, 19h11
  2. Tableau dynamique de pointeurs sur const char*
    Par Le Mérovingien dans le forum Débuter
    Réponses: 6
    Dernier message: 05/06/2008, 14h23
  3. STL, pointeurs et const... confusion!
    Par vdumont dans le forum SL & STL
    Réponses: 2
    Dernier message: 12/05/2006, 20h51
  4. Réponses: 7
    Dernier message: 02/12/2005, 13h02
  5. Chaines et pointeurs mais pas "const"
    Par hpfx dans le forum C
    Réponses: 9
    Dernier message: 05/10/2003, 20h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo