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 :

Mystère avec un tableau passé en paramètre.


Sujet :

C

  1. #1
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut Mystère avec un tableau passé en paramètre.
    Bonjour à tou(te)s,

    je suis tombé sur un comportement étrange de mon compilateur C (Visual Studio 10) !

    J'ai un type tableau d'entier.
    J'ai un fonction avec un paramètre de ce type.
    Dans la fonction je veux un pointeur sur ce paramètre.
    --> pas moyen d'avoir du code sans warning autrement qu'en ajoutant un cast affreux !

    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
     
    typedef int foo [5] ;
     
    int aze ( foo f )
        {
        // foo * ff = f ;     // code qui marche mais avec warning (les niveaux d'indirection de 'foo (*)' et de 'int *' sont différents)
        // foo * ff = &f ;    // code qui semble logique mais avec warning (les niveaux d'indirection de 'foo (*)' et de 'int **' sont différents) et plantage !
        foo * ff = (foo*)f ;  // obligé d'ajouter ce cast moche et pas très logique pour éviter le warning
        return (*ff)[0] ;
        }
     
    int main ()
        {
        foo f = { 654 } ;
        int x = aze( f ) ;
        return x ;  // tout est ok : x == 654
        }
    Y a-t-il un moyen propre de faire ça ?
    Ici la boule de gomme, à vous les studieux !

    PS : oui je sais, ce bout de code ne sert à rien... c'est juste une version ultra simplifiée qui met en évidence mon problème.

  2. #2
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 72
    Par défaut
    Bonsoir

    return f[0]; il en veut pas?????????????

  3. #3
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 72
    Par défaut
    en fait quand tu passes foo f en parametre il convertit le parametre en int [] en int * (merci dalfab)
    donc à l'intérieur de la fonction aze f n'est plus un foo mais un int[] un int *

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    On est dans le cas de la conversion implicite d'un tableau en pointeur. Qui est ici encore masqué par l'utilisation d'un typedef.
    On ne peut ni passer en paramètre ou ni retourner un tableau, c'est impossible.
    En écrivant int aze( foo f ) cela est vu comme int aze( int f[5] ) qui est interprété en int aze( int* f), le tableau est devenu pointeur.
    puis foo *ff = f; est vu int (*ff)[5] = f; qui produit un warning en C, une erreur en C++.

    On ne peut pas passer un tableau en paramètre, donc écrire int aze( foo f ) n'amènera qu'à du code trompeur. Si foo était une structure, on pourrait mais passer une structure par valeur est à éviter.
    Alors à tout prix éviter les typedef sur un tableau (et même sur pointeur) pour éviter un code 'trompeur'
    Ce que l'on peut faire de propre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct { int f[5]; } foo;  // une structure peut être utilisée sans piège
     
    int aze( const foo *pf ) {  // préférer passer une structure par adresse
        const foo* ff = pf;
        return ff->f[0];
    }

  5. #5
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut

    Ça fait un sacré bail que je code en C, et je n'étais jamais tombé sur ce cas...

    Merci dalfab, j'ai pu arranger un peu mon code pour éviter cette mocheté !

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 827
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Ce qui tue ton code c'est ce typedef. Surtout que masquer une info primordiale (savoir ce qui est un tableau ou un pointeur) derrière un type c'est le meilleur moyen de se crasher (la preuve...)

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int aze (int f[5])
    {
    	int *pt=f;
    	return *pt;  // ou return pt[0]
    }
     
    int main ()
    {
    	int f[5] = { 654 } ;
    	int x = aze( f ) ;
    	printf("x=%d\n", x) ;  // tout est ok : x == 654
    }

    Une fois que tu as compris que ton tableau 1D est vu comme un pointeur, tu peux réutiliser ton type. Perso je le déconseille mais si tu tiens vraiment, essaye alors de nommer ton type "t_xxx" pour coller aux conventions...

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    typedef int t_foo [5];
     
    int aze (t_foo f)
    {
    	int *pt=f;
    	return *pt;  // ou return pt[0]
    }
     
    int main ()
    {
    	t_foo f = { 654 } ;
    	int x = aze( f ) ;
    	printf("x=%d\n", x) ;  // tout est ok : x == 654
    }

    Pour résumer, t'avais en fait simplement oublié qu'un tableau est vu comme un pointeur donc il te faut un pointeur dans ta fonction et non un "t_foo"...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 07/08/2008, 14h09
  2. problème avec un tableau passé en paramètre
    Par curley dans le forum Débuter
    Réponses: 1
    Dernier message: 28/10/2007, 02h54
  3. Tableau passé en paramètre
    Par NeMo_O dans le forum C
    Réponses: 4
    Dernier message: 08/03/2007, 18h59
  4. Réponses: 32
    Dernier message: 24/07/2006, 19h19
  5. Réponses: 6
    Dernier message: 28/05/2004, 09h39

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