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 :

Questions de base sur les pointeurs et tableaux


Sujet :

C

  1. #1
    Membre éclairé
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Points : 803
    Points
    803
    Par défaut Questions de base sur les pointeurs et tableaux
    Considérons le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    char foo1[] = "foobar";
    char foo2[10] = "foobar";
    char *foo3 = "foobar";
    char *foo4;
    foo4 = "foobar";
    Je suis pas mal convaincu que les deux premiers assignations sont correctes. Les deux autres me chicottent un peu. En gros, je vois qu'on déclare un pointeur vers un char, mais on dit pas à quel endroit pointer et ensuite on assigne un string à cette adresse. Pourriez-vous m'éclairer sur les points suivants:

    1. Est-ce que les deux déclarations et assignations par pointeur sont correctes et légales?
    2. Y a-t-il des risques d'overlap de mémoire?
    3. Si c'est légal, est-ce que "foobar" représente une adresse en mémoire?

    Merci

  2. #2
    Membre éclairé Avatar de |PaRa-BoL
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 738
    Points : 876
    Points
    876
    Par défaut
    Salut,

    Est-ce que les deux déclarations et assignations par pointeur sont correctes et légales?
    Oui

    2. Y a-t-il des risques d'overlap de mémoire?
    Non

    3. Si c'est légal, est-ce que "foobar" représente une adresse en mémoire?
    Ton pointeur contiendra l'adresse de la constante "foobar".

  3. #3
    Membre éclairé
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Points : 803
    Points
    803
    Par défaut
    Je remarque que ceci me donne un segfault:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char *foo = "foobar";
    foo[5] = 'z';
    Quelle explication?

  4. #4
    Membre expérimenté
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 729
    Points
    1 729
    Par défaut
    Salut,

    A part lorsqu'elles sont utilisées pour initialiser des tableaux de caracteres (2 premiers cas), les chaines litterales sont stoquées dans une zone non modifiable. Le compilateur crée en fait un tableau de caracères juste assez grand pour y mettre les caractères et le \0 (en tout cas c'est ce que fait gcc). Les elements de ce tableau sont accesibles durant tout le programme, en fait c'est un peu comme si on avait un tableau global
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static const char tabchar[] = "abc";
    Lorsqu'on fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const char * abc = "abc";
    on fait pointer abc sur le premier caractère du tableau de caractères qu'aura créé le compilateur pour la chaine litterale.
    Si ton compilateur a accepté
    c'est qu'il est mal configuré car "abc" est de type "tableau de caracteres constants" directement convertible en "pointeur vers caractere constant" mais pas en "pointeur vers caractere modifiable"

  5. #5
    Membre éclairé
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Points : 803
    Points
    803
    Par défaut
    Ah, si je comprends ce que tu me dis Gruik, les deux lignes suivantes ne sont pas équivalentes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char foo[] = "foobar";
    char *bar = "foobar";
    Car je peux modifier foo, mais pas bar. Est-ce bien ça?

  6. #6
    Membre expérimenté
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 729
    Points
    1 729
    Par défaut
    Oui, et elles n'ont pas le meme sens non plus car dans le premier cas on gere notre tableau et on l'initialise, dans le deuxieme cas on laisse le compilateur créer un tableau caché constant et on recupere l'adresse du premier element

  7. #7
    Membre éclairé
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Points : 803
    Points
    803
    Par défaut
    J'imagine que si je voulais avoir un char* qui soit modifiable, il faudrait soit que je le fasse pointer vers un char[] ou utiliser malloc()?

  8. #8
    Membre expérimenté
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 729
    Points
    1 729
    Par défaut
    Lorsqu'on fait evaluer une variable tableau dans une expression, on obtient l'adresse du premier element soit un pointeur sur cet element
    Donc oui tu peux faire pointer une variable "char *" sur un tableau de char, à condition que ça ait une utilité... par exemple ce n'est pas parce que strcpy() attend un "char *" en paramètre qu'il faut avoir une variable "char *"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char foo[] = "foobar";
    strcpy(foo, "barfoo"); /* ca passe */
    Attention à la taille du tableau créé, que ce soit avec une taille indiquée entre les crochets ou avec un tableau initialisé.

    malloc() est un autre moyen (plus problematique) d'obtenir un tableau de char modifiable.

  9. #9
    Membre éclairé
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Points : 803
    Points
    803
    Par défaut
    Merci pour ces informations, Gruik. Maintenant la météo avec Colette.

  10. #10
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par |PaRa-BoL Voir le message
    Ton pointeur contiendra l'adresse de la constante "foobar".
    Huh ! "Adresse de la constante", je le sens mal...

    Une des caractéristiques des constantes (ou expressions constantes) est qu'elles n'ont pas d'adresse. Elles ne peuvent donc pas être des 'L-values' (partie gauche d'une instruction d'affectation).

    Une chaine littérale (string literal) est un tableau de char initialisé, terminé par un zéro, placé dans une zone mémoire qui n'est pas garantie d'être modifiable.

    Mais techniquement, on peut demander au compilateur de générer du code pour écrire dedans,
    même si l'exécution invoque un comportement indéfini. Une chaine littérale n'est donc pas une 'constante', mais un tableau de char initialisé non modifiable. Le tableau est anonyme mais il a l'adresse du son premier caractère.

    Il est d'ailleurs fortement conseillé de qualifier les pointeurs vers ce type de chaine de 'const'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       char const *s = "hello";
    qui ne veut évidemment pas dire 'constante', mais 'lecture seule' (le mot clé 'readonly' à la place de 'const' a malheureusement été refusé par le comité C).

  11. #11
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par GnuVince Voir le message
    J'imagine que si je voulais avoir un char* qui soit modifiable, il faudrait soit que je le fasse pointer vers un char[] ou utiliser malloc()?
    Oui.

  12. #12
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Gruik Voir le message
    Si ton compilateur a accepté
    c'est qu'il est mal configuré car "abc" est de type "tableau de caracteres constants" directement convertible en "pointeur vers caractere constant" mais pas en "pointeur vers caractere modifiable"
    Attention à ne pas confondre constant et const.

    'const' signifie 'readonly' (lecture seule). En aucun cas, il a le sens de constante (ou expression constante).

    Le fait qu'une chaine littérale soit non modifiable (lecture seule) ne signifie nullement que ce soit une constante.

    J'ai quand même lu cette erreur 2 fois ce soir...

  13. #13
    Membre expérimenté
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 729
    Points
    1 729
    Par défaut
    Oui c'est vrai que c'est pas parcequ'une variable est const qu'elle ne peut pas être modifiée ailleurs

  14. #14
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Attention à ne pas confondre constant et const.

    'const' signifie 'readonly' (lecture seule). En aucun cas, il a le sens de constante (ou expression constante).

    Le fait qu'une chaine littérale soit non modifiable (lecture seule) ne signifie nullement que ce soit une constante.

    J'ai quand même lu cette erreur 2 fois ce soir...
    Voici un extrait de K&R2:

    Citation Envoyé par Kernighan & Ritchie, 2nd edition
    A string constant, or string literal, is a sequence of zero or more characters surrounded by double quotes, as in

    "I am a string"
    Effectivement, du point de vue de la norme, un litéral chaine de caractère n'est pas considéré comme une constante ou une expression constante.

    Thierry

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

Discussions similaires

  1. question de base sur les transactions
    Par nouraty dans le forum Débuter
    Réponses: 3
    Dernier message: 22/12/2010, 21h51
  2. question de base sur les pointeurs
    Par Ganondorf dans le forum Débuter
    Réponses: 4
    Dernier message: 26/08/2010, 17h07
  3. question de base sur les classes
    Par tanguy.L dans le forum Langage
    Réponses: 10
    Dernier message: 28/02/2008, 17h37
  4. Réponses: 15
    Dernier message: 15/10/2006, 16h52
  5. Question de base sur les classes
    Par deaven dans le forum C++
    Réponses: 3
    Dernier message: 27/11/2005, 16h20

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