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 de tableau


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 90
    Par défaut Problème de tableau
    bonsoir

    je débute en C++

    je crois que pour déclarer un tableau c'est : int a[] (avec dans les crochets la taille du tableau )

    dans un exercice je dois faire une fonction qui utilise un tableau et dans l'énoncé
    est indiqué ( int a[], int n)
    alors que n est la taille du tableau


    merci d'avance

  2. #2
    Membre très actif
    Profil pro
    Responsable technique
    Inscrit en
    Février 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Responsable technique

    Informations forums :
    Inscription : Février 2006
    Messages : 366
    Par défaut
    Sympa l'histoire pour s'endormir. lol
    Et la question c'est quoi?

  3. #3
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Citation Envoyé par romanticide
    alors que n est la taille du tableau
    Pourquoi alors que ?

    +1 pr ya pas de question.

  4. #4
    Membre émérite
    Profil pro
    Eleveur de cornichons
    Inscrit en
    Juin 2002
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Eleveur de cornichons
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 074
    Par défaut
    Salut et bienvenue sur les forums de Developpez

    C'est vrai qu'il faut que tu fasses des messages plus clairs à l'avenir parce qu'on ne comprend pas vraiment ce que tu demandes.
    Je vais prendre un risque et supposer. Quand tu passes un tableau en paramètre d'une fonction, celle-ci ne peut pas connaitre la taille de ton tableau. Il faut donc lui passer en paramètre la taille de celui-ci. Par contre, y'a le cas d'une chaine de caractères qui est un tableau de char terminé par le caractère '\0' donc dans ce cas, pas besoin de la taille car on sait quand s'arrêter.
    Voilà, j'espère que ça répond à ta question.

    Nas'

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut Un pointeur ne connait pas le nombre d'éléments qui le composent
    Salut,

    Un tableau est, en effet, déclaré sous la forme généreique de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TYPE NomTableau[taille tableau]
    L'astuce, c'est que NomTableau est alors en réalité un pointeur de TYPE, et qu'à ce titre, il ne sait qu'une chose: de combien de case mémoires il doit se décaler pour trouver l'élément suivant du tableau.

    Tant que tu travailles dans la portée dans laquelle tu as déclaré ton tableau (on va dire que tu l'a déclaré statitquement ), tu sais de combien d'éléments il est composé...

    Ainsi, si dans main(), tu écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    int main(int argc, char* argv[])
    {
        int entier[10];
    //la suite du prorgramme
    }
    tu sais pouvoir utiliser les entiers allant de entier[0] à entier[9] inclus.

    Tu déclare, par la meme occasion, un pointeur de type int et nommé entier
    (int *entier ) qui pointe sur le premier élément de ton tableau (entier[0])

    Seulement, quand tu va créer une fonction dans laquelle tu va fournir ton tableau d'entier en parametre sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int MaFonction(int argtab[])
    et que tu l'appellera sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    i=MaFonction(entier);
    dans main(), tu passera en fait... le pointeur vers ton tableau.

    Or un pointeur de tableau ne connait pas le nombre d'éléments qui le composent...

    Bien sur, toi, tu sais que entier est un tableau de 10 entiers... Mais peux tu etre tout à fait sur que tu n'essayeras jamais d'appeler MaFonction en fournissant un autre tableau que le tableau entier?

    Et que ce passerait-il si, dans MaFonction, tu te basais d'office sur une taille de tableau de 10 entiers?

    Deux solutions sont envisageables, et susceptibles de poser des problemes:

    Soit tu fournis un tableau de moins de dix entiers (int montab9[9]), soit tu fournis un tableau de plus de dix entiers (int montab11[11]).

    Dans le premier cas (en fournissant un tableau de 9 entiers seulement), si tu fais une boucle du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for(int i=0;i<10;i++)
    {
        //acces à argtab[i];
    }
    Les éléments de tableau allant argtab[0] à argtab[8] réagiront correctement... mais argtab[9], ne faisant plus partie du tableau aura un comportement indéfini.

    Tu ne peux en effet absolument pas etre certain de ce qui se trouve dans la case mémoire correspondant à argtab[9]

    Avec *beaucoup de chance*, les cases mémoires ne contiennent que des "crasses", mais avec "moins de chance", et ce sera le cas le plus fréquent, les cases mémoires contiennent des données utilisées ailleurs... et ta boucle ira peut etre modifier ces valeurs...

    Le deuxième cas est un peu moins problèmatique, mais provoqueras des erreurs de calcul...

    En effet, imaginons trente secondes que tu veuille obtenir la somme des valeurs mises dans le tableau.
    En te basant sur le fait que tu as 10 éléments du tableau, tu fera une boucle du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int somme=0;
    for(int i=0;i<10;i++)
    {
        somme+=argtab[i];
    }
    return somme;
    Sauf que, si tu passe un tableau de 11 entiers (montab11), tu ne caculeras jamais que... la somme des dix premiers (et que le résultat envoyé ne sera donc pas juste)...

    Donc, pour que ta fonction puisse travailler aussi bien avec un tableau de 9 entiers qu'avec un tableau de 128 entiers, il faut lui donner une information complémentaire: le nombre d'éléments compris dans le tableau...

    MaFonction devient donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int MaFonction(int argtab[], int taille)
    {
        int somme=0;
        for(int i=0;i<taille;i++)
        {
            somme+=argtab[i];
        }
        return somme;
    }
    et son appel devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    MaFonction(entier, 10);
    //OU---OU---OU---
    MaFonction(montab9,9);
    //OU---OU---OU---
    MaFonction(montab11,11);
    et cela pourra fonctionner quelle que soit la taille du tableau fournis en parametre
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    L'astuce, c'est que NomTableau est alors en réalité un pointeur de TYPE, et qu'à ce titre, il ne sait qu'une chose: de combien de case mémoires il doit se décaler pour trouver l'élément suivant du tableau.
    Pas du tout.
    NomTableau est un tableau et pas un pointeur, et il sait exactement combien d'éléments il contient.
    C'est fou tous ces gens qui confondent pointeurs et tableaux.

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par loufoque
    Pas du tout.
    NomTableau est un tableau et pas un pointeur, et il sait exactement combien d'éléments il contient.
    C'est fou tous ces gens qui confondent pointeurs et tableaux.
    Du moment que tu fournis le tableau en parametre à une autre fonction, la fonction qui le reçoit recoit un pointeur sur ce tableau, et ne connait plus la taille du tableau...

    Et, à tout hasard, essaye simplement une fois de définir un tableau, fusse-t-il statique, de 10 entiers et d'accéder à l'indice 10 ou 11 sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int entier[10];
    std::cout<<entier[11]<<std::endl;
    Tu te rendras compte que meme le tableau ne connait pas sa taille

    Et qu'il n'y a meme pas un avertissement du compilateur indiquant que tu fais quelque chose d'illégal.

    On parle bien ici de tableau C-Like, et non d'un éventuel vector de quelque chose
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    D'un autre coté, le nom du tableau est, effectivement, un pointeur sur le premier élément du tableau...

    Qu'il te suffise encore une fois de faire "le test du singe":
    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
     
    int main(int argc, char *argv[])
    {
        int entier[10];
        // initialilisons le tableau ;-)
        for(int i=0;i<10;i++)
            entier[i]=i;
        //un pointeur d'entier, initialisé sur le début du tableau
        int *pt=entier;
        // l'affichage des valeurs en utilisant le pointeur
        for(int i=0;i<10; i++)
        {
            std::cout<<*pt<<std::endl;
            pt++;
        }
        return 0;
    }
    Te faut il une preuve supplémentaire de ce que j'avance ?
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Te faut il une preuve supplémentaire de ce que j'avance ?
    Où tu vois des preuves ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int foo[10];
    int* bar = foo;
     
    sizeof foo == 10*sizeof(int)
    sizeof bar == sizeof(int*)
    Donc un tableau connait sa taille.

    Ensuite,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int foo[10];
    int*& bar = foo;
    erreur, normal foo n'est pas un pointeur.
    Il y a création d'un temporaire qu'on refuse de référencer (ça fonctionne avec int* const & par contre)

    Et enfin, le passage de tableau
    On a là un type incomplet, qui est donc incapable de nous dire quelle est la taille du tableau, passé par référence.
    On a là le tableau normal, passé par référence.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void foo(int tab[n], size_t n)
    On a là le tableau avec la taille déduite du second argument, passé par référence. (C99 qui marche sur aucun compilateur)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template <size_t N> void foo(int (&tab)[N])
    On a là le tableau avec la taille déduite à la compilation (C++). Passage par référence explicite.

    Enfin un petit exemple avec deux dimensions.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void foo(int tab[10][10])
    Classique.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void foo(int (*tab)[10])
    Pas de problème, un tableau est implicitement convertible vers un pointeur vers son premier élément
    Type incompatible
    Type incomplet. Il semble néanmoins que cela ne fonctionne pas en C++ d'après ma mémoire.
    On remarquera qu'il est impossible avec ce type de faire appel à l'opérateur [], car celui-ci nécessite de connaître la taille des dimensions internes.

  10. #10
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Décidément, tu devrais apprendre à lire un peu ce que les gens écrivent...

    D'abord, quand tu écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sizeof foo == 10*sizeof(int)
    C'est TOI qui indique la taille... ce n'est nullement le tableau qui la connait de lui meme

    Ce qu'il connait, par contre, c'est la taille utile de ses élément... et par conséquent du nombre de cases mémoires dont il doit bouger pour accéder à l'élément suivant.

    Quand tu écris une fonction du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void foo(int tab[])
    tu fournis un tableau, mais tu n'indiques pas sa taille...

    Toute tentative d'accéder à tab[nombre d'élément +1] sera acceptée, avec un résultat indéfini...

    Quand tu écrit une fonction du genre de
    tu indique expressément que tu prévois que le tableau contiendra dix éléments...

    Mais rien ne t'empeche de passer un tableau qui en contient plus ou moins, avec les problèmes que j'expliquais dans mon premier post

    Quand tu écris une fonction du genre de
    tu l'appellera généralement sous la forme de
    et tu auras bel et bien fournis un pointeur de pointeur...

    Tu n'as en outre absolument pas besoin de faire une convertion implicite sur le pointeur du premier élément sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void foo(int (*tab)[10])
    car le nom du tableau que tu fournis en argument EST un pointeur (ici du type int*) et qu'une simple assignation suffit.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Il semblerait que tu n'aies toujours pas compris. (cf. tes insinuations répétées qu'un tableau est un pointeur alors que j'ai déjà démontré par le code que cela n'était pas le cas)
    Le type int[10] est totalement distinct de int*, même s'il est convertible vers celui-ci.

    Ton truc foo(&nomtableau) est de type int(*)[10][10] qui n'est absolument pas convertible vers int**.
    L'idée même qu'un tableau à deux dimensions puisse être convertible vers un pointeur vers un pointeur montre une totale incompréhension de ce que sont les tableaux.

    C'est TOI qui indique la taille... ce n'est nullement le tableau qui la connait de lui meme
    C'est moi qui définit le type, mais ce type contient parfaitement l'information de taille du tableau.

    Toute tentative d'accéder à tab[nombre d'élément +1] sera acceptée, avec un résultat indéfini...
    Les tableaux n'ont jamais eu l'objectif de faire cette vérification parfaitement inutile.

    Tu n'as en outre absolument pas besoin de faire une convertion implicite sur le pointeur du premier élément sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void foo(int (*tab)[10])
    car le nom du tableau que tu fournis en argument EST un pointeur (ici du type int*) et qu'une simple assignation suffit.
    Bien sûr que non.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int (*tab)[10] = 0;
    int* foo = tab; // ne fonctionne pas
    Normal, non seulement les types ne sont pas compatibles, et même s'ils l'étaient ils resteraient des types différents.

    Il est évident que tu connais très mal le système de types de C et de C++, aussi je te conseille de lire les standards appropriés.

  12. #12
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Sauf que, quand tu regarde
    tu seras d'accord avec moi pour dire que tableau, pris seul, correspond "à l'adresse mémoire à laquelle se trouve le premier élément du tableau"

    Or, la définition meme d'un pointeur c'est "une variable qui contient une adresse mémoire"...

    Sémantiquement parlant, tableau est donc bel et bien un pointeur... Meme si on peut estimer le terme mal choisi.

    Ensuite, quel que soit le type utilisé pour le tableau, si tu l'a défini comme étant un tableau de N élements, rien ne t'empeche de tenter d'accéder à l'élément N+1, N+10 ou N+152.

    Aucun compilateur ne te présentera le moindre avertissement sur le fait que tu es hors limite...

    Ce ne sera qu'à l'exécution que tu obtiendra un comportement indéfini...

    Tu peux donc définir, sur base des informations qui ont permis la création de ton tableau, une valeur qui corresponde à la taille de celui-ci, mais ton tableau en tant que tel ne connait pas sa taille...

    Ce qu'il connait, c'est la taille nécessaire à ses éléments (telle que char=1<=int<=float<=double ou des types définis par l'utilisateur)

    Je le répete encore une fois, on parle ici bien de tableau C-Like et non d'une utilisation de std::vector<un type>

    Si tu obtenais au minimum un avertissement sur le fait que tu essaie d'accéder à un élément hors limite, on aurait pu estimer qu'un tableau connaissait sa taille, mais... ce n'est pas le cas...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  13. #13
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Un tableau est un tableau et pas un pointeur, la norme est claire sur le sujet bien qu'il y ait quelques signes qui peuvent induire en erreur:
    - dans la plupart des contextes, un tableau est converti implicitement en un pointeur vers son premier élément,
    - les tableaux sont des types de seconde zone (on ne peut pas les affecter sauf à les mettre dans une structure), ce qui amplifie le problème précédent,
    - dans la déclaration de fonction, un [] permet de déclarer des pointeurs,
    - l'opérateur [] s'applique à des pointeurs,
    - ...
    mais confondre les deux est problèmatique tôt ou tard.

    Par exemple, si on utilise le contexte:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char tab[11];
    char mat[11][11];
    char (*ptr)[11];
    - sizeof(tab) = 11, j'ai jamais vu de pointeurs avec une telle taille;
    - ++ptr va avancer au tableau suivant, pas au pointeur suivant,
    - mat[3], *ptr se comportent exactement comme tab, donc il n'y a rien de particulier en ce qui concerne le nom d'une variable tableau,
    - et je ne vais pas aborder ce qui se passe avec les templates.

  14. #14
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par loufoque
    Et enfin, le passage de tableau
    On a là un type incomplet, qui est donc incapable de nous dire quelle est la taille du tableau, passé par référence.
    Non. C'est parfaitement équivalent àil s'agit d'un pointeur. On peut d'ailleurs prototyper avec une forme et définir avec une autre sans problème.

    On a là le tableau normal, passé par référence.
    À nouveau on a simplement un pointeur. Le 10 est autorisé mets ne sert à strictement rien.

    Enfin un petit exemple avec deux dimensions.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void foo(int tab[10][10])
    Classique.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void foo(int (*tab)[10])
    Pas de problème, un tableau est implicitement convertible vers un pointeur vers son premier élément
    Les deux déclarations sont à nouveau parfaitement équivalentes.

    Type incomplet. Il semble néanmoins que cela ne fonctionne pas en C++ d'après ma mémoire.
    Ni en C, ni en C++.

  15. #15
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par koala01
    Quand tu écris une fonction du genre de
    tu l'appellera généralement sous la forme de
    et tu auras bel et bien fournis un pointeur de pointeur...
    Essaye avant d'affirmer.

  16. #16
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Salut,

    +1 pour loufoque.

    De plus, pour l'histoire des "hors limites", tu peux facilement comprendre que dans une boucle ou une demande d'accès au n-ième élément d'un tableau mais d'une manière non déterminée à la compilation, le compilateur ne pourra jamais savoir si c'est bien dans les limites du tableau ou non.
    Alors lui imposer cette vérification qui ne sera pas toujours utile, voir rarement, rajoutant un temps de compilation non négligeable et tout, ce serait bof.
    Autant user de la rigueur à outrance à la place.

  17. #17
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Au fait, dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int tab[10];
     
    int x = tab[3];
    On a tab qui est utilisé dans un contexte où il est converti implicitement en un pointeur vers son premier élément, ensuite on a l'opérateur[] qui est appliqué à un pointeur vers int et à un entier.

    Je n'ai vraissemblablement pas relevé toutes les erreurs qui sont dans cette discussion.

  18. #18
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Non. C'est parfaitement équivalent à
    il s'agit d'un pointeur. On peut d'ailleurs prototyper avec une forme et définir avec une autre sans problème.
    La norme dit bien qu'il s'agit de deux types différents, et dit bien qu'il s'agit d'un type incomplet.
    Il est vrai, néanmoins, que le sizeof est équivalent à celui d'un pointeur.

    À nouveau on a simplement un pointeur. Le 10 est autorisé mets ne sert à strictement rien.
    Il sert à ce que sizeof tab vaille sizeof(int)*10, par exemple.

    Les deux déclarations sont à nouveau parfaitement équivalentes.
    Toujours pas non.

    Ni en C, ni en C++.
    Parfaitement autorisé par C.
    Je ne sais d'ailleurs pas pourquoi cela n'est pas autorisé par C++, peut-être n'apprecient-ils pas les types incomplets qui ne se simplifient pas à un pointeur.

  19. #19
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par loufoque
    La norme dit bien qu'il s'agit de deux types différents, et dit bien qu'il s'agit d'un type incomplet.
    Il est vrai, néanmoins, que le sizeof est équivalent à celui d'un pointeur.
    Où? Pour le C++ commence par 8.3.5/3, et pour le C 6.7.5.3/7.

    Il sert à ce que sizeof tab vaille sizeof(int)*10, par exemple.
    À part évidemment que sizeof tab vaut sizeof int*.
    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
    $ cat loufoque.cc
    #include <iostream>
     
    void f(int tab[10])
    {
      tab = new int[20];
      std::cout << sizeof(tab) << std::endl;
    }
     
    int main()
    {
      f(NULL);
    }
    $ como -o loufoque loufoque.cc
    Comeau C/C++ 4.3.3 (Oct 24 2003 16:00:23) for RedHat_LINUX_INTEL_ELF
    Copyright 1988-2003 Comeau Computing.  All rights reserved.
    MODE:strict errors C++
     
    "loufoque.cc", line 3: warning: parameter "tab" was set but never used
      void f(int tab[10])
                 ^
     
    $ ./loufoque
    4
    Toujours pas non.
    Il faut vérifier avant de s'avancer. Même moi quand j'oublie de le faire,
    je me trompe. La preuve suit:

    Type incomplet. Il semble néanmoins que cela ne fonctionne pas en C++ d'après ma mémoire.
    Ni en C, ni en C++.
    Parfaitement autorisé par C.
    Exact.

  20. #20
    Membre expérimenté
    Avatar de David Fleury
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 253
    Par défaut
    hum, j'ai douté donc j'ai essayé (sans avoir le courage de lire la norme)

    en C++ (je ne connais pas le C)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void foo( int t[10] ) {}
    void foo( int t[] ) {}
    void foo( int *t ) {}
    ces 3 signatures semblent être identiques pour mon compilo au vu de l'erreur de compilation, ce qui laisse supposer que le type des paramètres est identique.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    .\main.cpp(13) : error C2084: la fonction 'void foo(int [])' a déjà un corps
            .\main.cpp(11) : voir la définition précédente de 'foo'
    Mais il est évident qu'en C++, j'utiliserai dans 99% des cas en std::vector
    (et ici sûrement ici avec un passage par référence constante)

Discussions similaires

  1. Débutant en Javascript : problème de tableau !
    Par bluheim dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 06/11/2005, 16h03
  2. [XHTML] problème de tableau
    Par virgul dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 28/04/2005, 08h18
  3. Problème de tableau
    Par tom06440 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 26/04/2005, 21h30
  4. Problème de tableau
    Par krfa1 dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 08/02/2005, 12h09

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