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 :

problème sur tableau de string


Sujet :

C

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut problème sur tableau de string
    Bonjour

    voici mon code :
    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
     
    int parseArgs(const char* arg_list[], int arg_nb){
    ...
    // => la fonction ne change pas le contenu des cahines pointées par arg_list
     
    }
     
     
    int main(void){
     
    	char* arg_list[4]; // tableau de pointeur de string
     
    	strcpy(arg_list[0], "toto");
    	strcpy(arg_list[1], "tutu");
    	strcpy(arg_list[2], "titi");
    	strcpy(arg_list[3], "tata");
     
    	parseArgs(arg_list, 4);
    }
    Dans la déclaration de ma fonction, le mot "const" dans "const char* arg_list[]" veut bien dire "la valeur pointée par le pointeur qui est dans le tableau arg_list[] ne peut être modifiée à l’intérieur de la fonction" ?

    Si c'est le cas, alors pourquoi le compilo me renvoi comme erreur (sur l'appel de la fonction) :
    note: expected 'const char **' but argument is of type 'char **'

    Remarque : le code suivant ne génère pas de warning :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void fooConst(const char *str){
    ...
    }
     
    int main(void){
    	char *myStr = "hello world";
     
    	fooConst(myStr); // pas de warning
    }

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    http://c.developpez.com/faq/index.ph...OINTEURS_const --> cette entrée de la FAQ devrait t'intéresser. Si tu échanges la position de const et char* dans la définition de ta fonction, tu n'as plus le warning.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    bonjour,

    je ne suis pas sure de tout comprendre.

    Ce que je veux définir : c'est un tableau qui contient des pointeurs qui pointe sur quelque chose de constant. Ce n'est pas le cas de ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    	char const * arg_list[4] = {"toto", "tutu", "titi", "tata"}; 
    	const * arg_list2[4] = {"toto", "tutu", "titi", "tata"};
     
    	arg_list[0] = "roro"; // je peux bien changer modifier les valeurs de mon tableau
    	char const * ptStr = arg_list[0]; ptStr = "roro"; // fait la même chose que la ligne précédente
     
    	//arg_list[0][0] = 'a'; // génère bien une erreur
    	//ptStr[0] = 'a'; // génère bien une erreur
     
    	foo(arg_list2, 4); // affiche ma liste
    	// => génère un warning
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void foo(char const * *argv,  int argNb){
    	int i;
     
    	for(i=0; i<argNb; i++){
    		printf("%s\r\n", argv[i]);
    	}	
    }
    => je ne vois pas pourquoi avec arg_list2 j'ai un warning : on peut bien passer une variable non constante à une fonction qui attend une variable constante, non ?

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Dans ce cas, ce n'est pas uniquement dans la fonction que tu souhaites que les chaînes soit non modifiables, c'est tout le temps ?

    Si je ne m'abuse, "const char* arg_list[]" est tableau contenant des pointeurs sur const char (chaînes non modifiables).

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int parseArgs(const char* arg_list[], int arg_nb)
    {
        printf("Fonction parseArgs");
        return 0;
    }
     
    int main(void){
     
        const char* arg_list[4]; // tableau de pointeur de string
     
        const char* chaine1 = "bonjour";
        const char* chaine2 = "je";
        const char* chaine3 = "suis";
        const char* chaine4 = "Bktero";
     
        //*(chaine4)="b"; // genere une erreur, chaine4 pointant sur une zone constante
        chaine4="Pierre"; // autorise, le pointeur n'est pas constant
     
        arg_list[1]=chaine1;
        arg_list[2]=chaine2;
        arg_list[3]=chaine3;
        arg_list[4]=chaine4;
     
        parseArgs(arg_list, 4);
     
        return 0;
    }
    Si tu reprends le code de ton premier message et que tu déclares arg_list comme moi (avec le const), tu verras les soucis. Tu ne peux pas copier avec strcpy dans une zone déclarée comme constante (d'ailleurs, tu n'as pas alloué les zones mémoires avec strcpy !) Je n'arrive pas à expliquer pourquoi ta fonction fooConst ne provoque pas de warning par contre....


    Dans ton 2e message, n'aurais tu pas oublié un char dans "const * arg_list2[4] = {"toto", "tutu", "titi", "tata"};". Le code ne compile pas chez moi. Si je le rajoute, je n'ai pas de warning sur l'appel à foo. Je suis d'accord avec tes autres commentaires. D'ailleurs, tu peux réécrire la définition de la fonction ainsi "void foo(const char *argv[], int argNb)", pour retrouver ce que tu fais dans parseArgs de ton premier message.

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Dans ton 2e message, n'aurais tu pas oublié un char
    Oui effectivement : c'est bien ça que je voulais écrire


    Citation Envoyé par Bktero Voir le message
    Si je ne m'abuse, "const char* arg_list[]" est tableau contenant des pointeurs sur const char (chaînes non modifiables).
    Donc c'est bien ce que je veux faire



    Citation Envoyé par Bktero Voir le message
    Dans ce cas, ce n'est pas uniquement dans la fonction que tu souhaites que les chaînes soit non modifiables, c'est tout le temps ?
    Non, c'est bien là le problème : je veux pouvoir modifier mes chaines en dehors de la fonctions (donc déclarer arg_list sans le mot "const") mais que le compilateur me génère une erreur si je tente de les modifier à l'intérieur de ma fonction la chaine.
    En gros, je veux faire une fonction qui accepte en entrée des chaines modifiables et non modifiables => c'est par exemple le cas de la fonction strcpy :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char * strcpy ( char * destination, const char * source );


    Citation Envoyé par Bktero Voir le message
    Je n'arrive pas à expliquer pourquoi ta fonction fooConst ne provoque pas de warning par contre....
    Chez toi aussi, il ne provoque pas d'erreur ?
    Voici mon explication (à confirmer, je dis peut-être n'importe quoi :
    Une variable 'const' est une variable dont on ne peut changer la valeur mais on peut la lire => donc on peut très bien affecter dans une variable 'non const' une valeur de variable 'const'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    char var;
    const char cvar = 'a';
     
    var = cvar; // normalement pas de warning
     
    // par contre l'inverse n'est pas possible :
    cvar = var;
    Donc il me semble tout à fait normal que l'on puisse caster un pointeur de char sur un pointeur de const char vu que tout ce qu'il est possible de faire sur un const char (c'est à dire faire de la lecture) est faisable sur un char
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    char *ptVar;
    const char *ptcVar;
     
    ptcVar = &cvar;
    ptVar = &var;
     
    ptcVar = ptVar; // normalement pas de warning
     
    // par contre l'inverse n'est pas possible :
    // => car ptVar à le droit de modifier la valeur donc ça serait dangereux
    ptVar = ptcVar;
    => est-ce que tu es d'accord avec moi ? tu comprend pourquoi ça marche maintenant ?
    => Si ce que j'ai dit est donc vrai, je ne comprend pas pourquoi mon premier exemple ne fonctionne pas : ne devrait-il pas y avoir un cast implicite dans mon premier exemple et donc ne pas générer de warning ?

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    D'ailleur je viens de penser que vu que ma fonction ne va modifier aucun élément de arg_list, le prototype de la fonction devrait plutôt être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int parseArgs(const char * const * arg_list, int arg_nb);
    => mais ça ne change rien

  7. #7
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Ca commence à partir un peu partout, restons concentrés

    La première chose à faire, c'est définir clairement le type de variable que tu souhaites avoir et ce que tu souhaites pouvoir faire (ou ne pas pouvoir) faire dans ta fonction. Si j'ai bien suivi, tu veux définir dans ton main un tableau de pointeurs sur chaînes constantes. On est donc d'accord sur cette déclaration :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const char* arg_list[4];
    Tu veux passer ce tableau en paramètre d'une fonction et dans cette fonction, tu souhaites que les pointeurs ne puissent pas être modifiés (les chaînes pointées par ces pointeurs sont toujours, de part la définition d'arg_list, non modifiables). Pour cela, il faut faire ce que tu as fait dans ton dernier message : le paramètre doit attendre des pointeurs constants sur chaînes constantes. On retrouve là le dernier point abordé dans le lien que je t'ai donné au début.

    La deuxième chose à faire est de parler de fooConst
    Effectivement, je n'ai pas non plus de warning à la compilation. Je partage ton explication (si je l'ai bien comprise ^^). On peut considérer un char comme un const char, mais pas l'inverse. En effet, les opérations réalisables sur un const char peuvent être fait sur un char, mais l'inverse n'est pas vrai. J'ai par exemple fait le code suivant qui semble confirmer notre hypothèse commune :
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    void fooConst(const char *str){
        printf("Fonction fooConst, str = %s\n", str);
    }
     
    void fooNonConst(char *str){
        printf("Fonction fooNonConst, str = %s\n", str);
    }
     
    int main(void){
     
        char * arg="bonjour";
        fooConst(arg); // ne genere pas de warning
     
        const char *argconst="au revoir";
        fooNonConst(argconst);  // genere un warning
     
        return 0;
    }
    La dernière chose à expliquer est le warning original. Il y a 2 possibilités pour : aucun cast n'est fait ou le cast fait n'est pas celui qu'on pense et les types ne sont donc pas compatibles. Mais mes connaissances et capacités de réflexion s'arrêtent là

    Arf ! J'ai quand même essayé quelque chose. Partant du message de warning, je me sis dit "tiens, c'est comme si la conversion en const n'était pas faite". J'ai donc modifié cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    parseArgs( (const char**) arg_list, 4);
    Et ça ne warn plus

    J'aimerais juste bien que quelqu'un viennent confirmer ou infirmer nos dires

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    j'ai fait encore quelques tests si ça peut guider quelqu'un pour savoir pourquoi mon premier exemple génère un warning :

    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
     
    void fooConstConstConst( const char * const * const argv, int argNb){
        int i;
     
        //const char * const list[4] = {"roro", "riri", "ruru", "rara"};
        //const char str0[10] = "riri";
        //argv[0] = str0; // génère une erreur
        //argv[0][0] = 'a'; // génère une erreur
        //argv = list; // génère une erreur
        // => a l'interieur de cette fonction, il me semble donc impossible de changer une des valeurs de argv
     
        for(i=0; i<argNb; i++){
            printf("%i : %s\n", i, argv[i]);
        }
    }
     
    void fooConst(char * * argv, int argNb){
     
        int i;
     
        for(i=0; i<argNb; i++){
            printf("%i : %s\n", i, argv[i]);
        }
     
    }
     
    int main()
    {
        const char * tab[4] = {"toto", "titi", "tutu", "tata"};
        // => variable de type "const char * *" et non pas "const char * const * const"
     
        char * tab2[4];
        char str0[10];
        char str1[10];
        char str2[10];
        char str3[10];
        strcpy(str0, "toto");
        strcpy(str1, "titi");
        strcpy(str2, "tutu");
        strcpy(str3, "tata");
        tab2[0] = str0;
        tab2[1] = str1;
        tab2[2] = str2;
        tab2[3] = str3;
     
        fooConstConstConst(tab, 4);
        fooConstConstConst(tab2, 4); // génère un warning
     
        fooConst(tab, 4); // génère un warning
        fooConst(tab2, 4);
     
        return 0;
    }
    => c'est bizarre que "fooConstConstConst(tab, 4);" ne génère pas de warning

Discussions similaires

  1. problème sur tableau, bloc et record?
    Par mohammed.badre dans le forum Débuter
    Réponses: 2
    Dernier message: 08/12/2011, 15h56
  2. Problème de tableau de string
    Par on2101 dans le forum MATLAB
    Réponses: 3
    Dernier message: 01/02/2011, 12h34
  3. problème sur tableau croiée dynamique
    Par flo64 dans le forum Access
    Réponses: 2
    Dernier message: 29/05/2006, 11h23
  4. problème our passer des string dans tableau d'int
    Par Battosaiii dans le forum C++
    Réponses: 9
    Dernier message: 15/07/2004, 17h42
  5. Réponses: 25
    Dernier message: 16/07/2003, 20h41

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