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 :

Identité entre deux types ? [Débutant(e)]


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 13
    Par défaut Identité entre deux types ?
    Bonjour tout le monde ,

    Dans un projet , j'ai rencontré une difficulté pour allouer un certain objet et c'est ce qui m'a amené à essayer d'analyser sa nature.
    Si l'on considère un objet tmp du type suivant déclaré dans le main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char ( * tmp ) [ ];
    Ce que j'ai compris , c'est que tmp est ici un pointeur sur un pointeur sur une zone de unsigned char , autrement dit un pointeur sur un tableau d'unsigned char .
    Si maintenant je déclare également un deuxième objet tmp2 du type suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char tmp2[10];
    Et si je fais pour tester l'égalite de nature , la chose suivante :
    J'obtiens par le compilateur le message suivant :
    invalid use of array with unspecified bounds

    Très bien , j'ai une intuition de l'endroit où ça peut venir , je n'ai pas spécifié de taille pour tmp.
    Mais à mon stade de compréhension , je ne sais pas encore pourquoi cette taille est nécessaire mais passons , mettons la taille en faisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    unsigned char ( * tmp ) [10];
    unsigned char tmp2[10];
    *tmp=tmp2;
    J'obtiens cette fois-ci de la part du compilateur le message suivant :
    incompatible types in assignment

    Je ne comprends pas cette situation .
    *tmp étant un pointeur sur un tableau de 10 unsigned char
    tmp2 étant un pointeur sur un tablea de 10 unsigned char
    Pour moi il y a identité des objets
    Pourquoi le compilateur n'est pas content ?
    *tmp n'est pas affectable ??

    Et également je n'arrive pas à allouer mon tableau *tmp via une fonction avec passage de tmp en argument .
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int Alloueblabla( unsigned char ( *tmp )[ ]  );
    Si dans le main j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char ( * tmp ) []=NULL;
    et que je souhaite allouer mon tableau *tmp , logiquement je ferai dans la fonction qui se chargerait de ce travail :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *tmp=( unsigned char * )malloc( taille adéquate );
    Mais j'obtiens error: invalid use of array with unspecified bounds

    J'arrive pas à cerner concrètement ce message d'erreur .
    Quelqu'un aurait-il un éclairement à me donner ??

    Merci beaucoup

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    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 832
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Black-Hawk Voir le message
    *tmp étant un pointeur sur un tableau de 10 unsigned char
    tmp2 étant un pointeur sur un tablea de 10 unsigned char

    Pour moi il y a identité des objets
    Exact

    Citation Envoyé par Black-Hawk Voir le message
    *tmp n'est pas affectable ??
    Exact aussi. On ne peut pas affecter l'adresse d'un tableau. Quand tu déclares "char tmp2[10]" ben tmp2 contient le début de la zone de 10 caractères (donc l'adresse) mais tu pourras jamais modifer "tmp2" (lui dire "change d'adresse").
    Ben c'est pareil pour "*tmp". "*tmp" est sensé contenir lui-aussi l'adresse d'un tableau de 10 caractères et aussi être invariant. Tout ce que tu peux faire, c'est dire "tmp=<truc>" en faisant en sorte que "*<truc>" soit le début d'un "char[10]" (par exemple en écrivant "tmp=&tmp2"...)

    PS: C'est bien de chercher à comprendre par toi-même
    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]

  3. #3
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char ( * tmp ) [ ];
    Ca peut pas compiler. cette déclaration dit que tmp est un pointeur, mais un pointeur sur quoi? char []? En C la dimension d'un tableau doit être donné, sauf dans une déclaration avec initialisation auquel cas le compilateur calculera la taille du tableau lui-même (oui on lui a appris à compter). Donc on peut faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned char (*tmp)[8]; /* pointeur sur un tableau de 8 caracteres */
    unsigned char (*tmp)[10]; /* pointeur sur un tableau de 10 caracteres */
    Mais surtout pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char (*tmp)[];
    Citation Envoyé par Black-Hawk
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    unsigned char ( * tmp ) [10];
    unsigned char tmp2[10];
    *tmp=tmp2;
    J'obtiens cette fois-ci de la part du compilateur le message suivant :
    incompatible types in assignment
    tmp étant un pointeur sur un unsigned char [10] et tmp2 étant un unsigned char [10], tu peux faire l'affectation suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tmp = &tmp2; /* on affecte à tmp l'adresse de la variable tmp2 */
    Je rappelle qu'un tableau est une variable comme toutes les autres bien qu'elle possède quelques propriétés quelque peu particulières. Une de ces propriétés est que le nom du tableau peut être interprété comme un pointeur vers son premier élément, mais celà ne signifie pas qu'un tableau est un pointeur : un tableau reste un tableau. Mais puisque le tableau réside en mémoire comme toutes les autres variables, il a une adresse (qui est numériquement égal à l'adresse de son premier élément).

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 13
    Par défaut
    Ok je vois , merci pour vos réponses

    Je savais qu'un tableau était quelque chose qui n'était pas affectable mais le fait d'utiliser un déclarateur absolue du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ( * tmp ) [ expression_constante ]
    m'a troublé.
    J'ai saisi que que *tmp ne peut pas être modifié.

    La déclaration de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char ( * tmp ) [ ]
    pour moi fonctionne avec gcc , c'est un pointeur , je pense que c'est pour ça qu'il crie pas à ce moment là.
    Cela compile mais en fait c'est incorrect et il me le dit des que j'essaye de l'utiliser .
    Ca doit venir de là son message error: invalid use of array with unspecified bounds.
    J'avais mal saisi que la taille dans la déclaration définissait également le type.

    Le problème c'est que dans mon projet , je connais pas la taille de mon tableau au moment de sa déclaration , c'est pour ça que j'ai voulu écrire ce genre de chose .
    Mais après avoir lu plus de choses sur le forum , je comprends mieux .
    Si je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned char ( * tmp ) [1];
    tmp=malloc( 10 * sizeof( *tmp ) );
    Je vais m'allouer 10 unsigned char qui seront rangés consécutivement en mémoire.

    Et puis aussi j'ai dit une bêtise en haut , j'ai toujours pensé qu'un tableau c'était un pointeur sur son premier élément , en fait c'est plutôt une adresse.
    Il n'y a pas de variable créee correspondant à l'identificateur contenant l'adresse du premier élément , c'est seulement l'identificateur qui est interpreté comme une adresse. Et c'est seulement dans les arguments de fonctions que cette fois-ci il y a création de pointeur .
    C'est ce que je viens de mieux comprendre après avoir lu divers sujet .

    Du coup pour mon allocation , je suis forcé de passer dans la fonction d'allocation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int AlloueBlabla( unsigned char ( ** tmp ) [1]  );
    Mon prof nous a donné un prototype avec un unique pointeur , je vois pas comment on peut faire autrement qu'augmenter un niveau d'indirection pour créer l'allocation du tableau .
    Avec un unique pointeur , l'allocation sera transparente dans l'environnement extérieur.
    Il a dû faire une erreur .

    Enfin je vais réfléchir encore un peu pour être sûr , c'est pas moi qui me plante.

  5. #5
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Citation Envoyé par Black-Hawk
    Le problème c'est que dans mon projet , je connais pas la taille de mon tableau au moment de sa déclaration , c'est pour ça que j'ai voulu écrire ce genre de chose .
    Dans ce cas utilise un simple pointeur sur unsigned char. Un tableau quelle que soit sa dimension est représenté en mémoire comme un simple tableau à une dimension. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char t[10][100];
    En mémoire, t n'a rien qui le différencie avec un tableau de 1000 unsigned char. Mais un unsigned char [10][100] n'a pas le même type qu'un unsigned char [1000], donc il faut un cast pour affetcter l'adresse d'un tableau à deux dimensions vers un unsigned char *.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned char t[10][100];
    unsigned char * p = (unsigned char *)t; / * on pointe sur t */
    Alors :

    p[100*i + j]

    Est équivalent à :

    t[i][j]

    Et donc pour passer un tableau à deux dimensions à une fonction, on passe l'adresse du premier lément puis les dimensions.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void f(unsigned char * p, size_t nLignes, size_t nColonnes)
    {
        ...
    }

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 13
    Par défaut
    Citation Envoyé par Melem Voir le message
    Dans ce cas utilise un simple pointeur sur unsigned char.
    Ouais c'est ce que j'aurais fait de moi même si j'avais été libre sur le type mais comme on m'impose d'utiliser un type du genre pointeur sur tableau de unsigned char , je suis les consignes.

  7. #7
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Citation Envoyé par Black-Hawk Voir le message
    Ouais c'est ce que j'aurais fait de moi même si j'avais été libre sur le type mais comme on m'impose d'utiliser un type du genre pointeur sur tableau de unsigned char , je suis les consignes.
    Si tu veux allouer tes tableaux dans une fonction,le plus logique est de retourner l'adresse des tableaux créés (ou NULL en cas d'échec) plutôt qu'un int. Pour créer N tableaux de M unsigned char, tu peux avoir par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    unsigned char (* Allocation (int N,int M)) []
    {
      return malloc(N*M);
    }
    et pour l'utiliser, par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #define N 10
    #define M 3
    int main(void)
    {
       unsigned char (*x )[N];
       x = Allocation(N,M);
      if(x!= NULL) 
      {
    ...
       x[i][j] = ...; 
    ...
    Comme la syntaxe de la déclaration de la fonction est ésotérique, on peut au préalable définir un type pour la simplifier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef  unsigned char ( *TpTab )[] ;
    TpTab Allocation (int N,int M)
    {
      return malloc(N*M);
    }
    Si tu veux réaliser ceci par l'intermédiaire de la liste des arguments :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int Allocation (TpTab* x,int N,int M)
    {
      *x = malloc(N*M);
      return  *x != NULL;
    }
     
    int main(void)
    {
       unsigned char (*x)[10];
       if(Allocation(&x,10,3))
       {
        ....
    ...

  8. #8
    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 Melem Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char ( * tmp ) [ ];
    Ca peut pas compiler.
    C'est un pointeur sur un type incomplet. Exactement comme struct t*. Il y a des choses qu'on ne peut pas faire (l'arithmetique par exemple), mais c'est valide.

  9. #9
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Oui je me rends compte. Merci pour les précisions.

Discussions similaires

  1. [PowerShell] Script pour basculer entre deux types de connexions / Adresse Ip
    Par GADENSEB dans le forum Scripts/Batch
    Réponses: 6
    Dernier message: 17/06/2014, 18h18
  2. dfférence entre deux type de codes
    Par napi15 dans le forum C++
    Réponses: 1
    Dernier message: 26/11/2010, 16h52
  3. [AC-2007] relations entre deux types different
    Par lovedesitaliens dans le forum Modélisation
    Réponses: 1
    Dernier message: 22/10/2010, 16h14
  4. Choix entre deux type de structures de tables
    Par Alerion dans le forum Débuter
    Réponses: 2
    Dernier message: 07/12/2009, 19h48
  5. Résultats erroné différence entre deux types TDateTime
    Par Alghero dans le forum C++Builder
    Réponses: 6
    Dernier message: 12/03/2004, 17h03

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