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 :

affectation de tableau (taille fixe)


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Par défaut affectation de tableau (taille fixe)
    Bonjour,
    J'ai un drôle de problème d'affectation.

    Contexte: pour me détendre un peu , j'explorais la question d'un type numérique décimal et à virgule fixe (je veux dire "fixed-point", pas sûr du terme en français). Le codage est en BCD compressé, c'est-à-dire avec un chiffre par quartet. Chaque nombre est un entier non signé de 32 bits (type défini "Natural"), donc au max 8 chiffres. Bon, ça marche: je peux lire et écrire des nombres (facile en passant par l'ascci), et même faire des additions!
    Je me suis vite rendu compte que c'est super galère d'accéder à des chiffres dans un demi-octet, aussi bien en lecture qu'en écriture, même en-dehors des histoires de shift et masques, simplement les prendre l'un derrière l'autre, et dans l'ordre inverse en plus pour toute opération.

    Alors mon but là était de définir un type de nombre dans lequel sont distincts les quartets/chiffres: D'abord un type struct "Bidigit" de la taille d'un octet mais comprenant 2 digits "low" et "high" définis grâce aux champs de bits de C. Et du coup un Natural est un tableau fixe de 4 Bidigits.
    (Je voudrais aussi savoir quel est le coût en temps d'avoir une struct de 2 quartets comme ça, plutôt qu'un octet, et un tableau de 4 octets plutôt qu'un entier non-signé de 32 bits.)
    (J'ai aussi un itérateur de digits qui me les passe un par un pour les opérations : ça, ça marche, et c'est super pratique; mais il reste à accéder aux chiffres en écriture.)
    Les types de nombres sont comme ci-dessous, avec un example qui montre mon problème :

    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
    // type for a pair of digits in an octet
    typedef struct Bidigit {
       unsigned char high : 4 ;
       unsigned char low  : 4 ;
    } Bidigit ;
     
    // a natural is 4 bidigits
    typedef Bidigit Natural [4] ;
     
    int main () {
       Natural n1 = {{0,1},{2,3},{4,5},{6,7}} ;
       Natural n2 ;
       n2 = n1 ;      // ********** erreur ??? **********
       return EXIT_SUCCESS ;
    }
     
    ==>
     
    natural2.c:229:7: error: incompatible types when assigning to type ‘Natural’ from type ‘struct Bidigit *’
    Alors là, je pige plus rien. Je peux pas assigner un T à un T ?

    Denis

    PS: j'ai esayé juste pour voir de "caster" de force n1 en Natural, et ça me donne une erreur de gcc que je comprends pas non plus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    int main () {
       Natural n1 = {{0,1},{2,3},{4,5},{6,7}} ;
       Natural n2 ;
       n2 = (Natural) n1 ;
       return EXIT_SUCCESS ;
    }
     
    ==>
     
    natural2.c:229:9: error: cast specifies array type
    Qu'est-ce que ça veut dire ? (Je comprends la lettre, mais pas le pourquoi du comment.)

    PPS : J'ai essayé de ruser, mias j'arrive pas à tromper gcc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    n2 = *((Natural*)(&n1)) ;
    ma donne la même erreur "incompatible types when assigning to type ‘Natural’ from type ‘struct Bidigit *’".

  2. #2
    Membre éprouvé Avatar de Flow_75
    Femme Profil pro
    Ingénieure
    Inscrit en
    Mai 2005
    Messages
    1 100
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieure
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 100
    Par défaut
    Salut,

    Pour copier un tableau, tu dois faire élément par élément.

  3. #3
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Je ne suis pas sûr de moi mais :
    Devrait marcher au moment de la déclaration de n2 non?

    Sinon, tu devrais essayer de définir un union :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    union
    {
          unsigned char;
          struct
          {
                unsigned char p1 : 4;// variable sur 4 bits?
                unsigned char p2 : 4;
           }moitie;
    }
    Ainsi si p1 et p2 sont contigües (faudra tester), tu pourras directement accéder à l'octet complet ainsi qu'aux deux demis-octets.

    Au pire si ceci ne marche pas, tu peux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    union
    {
               unsigned long int; //ton entier de 32 bits
               unsigned char[4];//tableau de 4x8 bits
    }
    Et tu n'auras qu'à créer une fonction qui retourne le premier quartet (return x & 0F) puis une autre qui retourne le second quartet (return x << 4).

  4. #4
    Membre confirmé
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Je ne suis pas sûr de moi mais :
    Devrait marcher au moment de la déclaration de n2 non?
    Non, ça marche pas: "invallid initialiser". Et en castant vers Natural explicitement j'ai à nouveau "error: cast specifies array type".

    Sinon, tu devrais essayer de définir un union :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    union
    {
          unsigned char;
          struct
          {
                unsigned char p1 : 4;// variable sur 4 bits?
                unsigned char p2 : 4;
           }moitie;
    }
    Ainsi si p1 et p2 sont contigües (faudra tester), tu pourras directement accéder à l'octet complet ainsi qu'aux deux demis-octets.
    Hum, ça peut résoudre un problème à venir, mais c'est pas celui auquel je me heurte là.

    Au pire si ceci ne marche pas, tu peux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    union
    {
               unsigned long int; //ton entier de 32 bits
               unsigned char[4];//tableau de 4x8 bits
    }
    Et tu n'auras qu'à créer une fonction qui retourne le premier quartet (return x & 0F) puis une autre qui retourne le second quartet (return x << 4).
    Voilà! Ca, c'est une idée... J'ai pas le réflèxe d'utiliser les unions pour changer de type (seulement quand il peut y avoir réellement plusieurs types de données). En fait, c'est un peu formaliser le genre de cast sauvage que je fais dans la première version de ce module.

    Merci beaucoup, je vais essayer et je ramène des pouvelles.
    Denis

  5. #5
    Membre confirmé
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Par défaut ca roule !
    Voilà mon dernier type:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // type for a pair of digits in an octet
    typedef struct Bidigit {
       unsigned char high : 4 ;
       unsigned char low  : 4 ;
    } Bidigit ;
     
    // a natural will hold 4 bidigits
    typedef Bidigit Bidigits [4] ;
     
    // a natural is a union with a binary value so as to be able to copy directly
    typedef union Natural {
       Bidigits octets ;
       uint     binary ;
    } Natural ;
    Donc, je peux lire, écrite globalement (en binaire), ou chiffre par chiffre en utilisant pa exemple :
    Et je peux copier globalement le binaire d'un coup.

    Pour ceux que ça intéresse, voilà mon "énumérateur de chiffres", qui me facilite bien la vie:

    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
    /// digit enumerator !!!
    typedef struct DigitsData {
       Natural n ;
       uint i ;
       bool end ;
       bool low_digit ;     // low (or high) digit in octet
    } DigitsData ;
    typedef struct DigitsData  * Digits ;
    Digits digits_new (Natural n) {
       Digits ds = malloc (1* sizeof(DigitsData)) ;
       VERIFY_MALLOC (ds) ;
       ds->n          = n ;
       ds->i          = digit_count ;
       ds->end        = false ;
       ds->low_digit  = false ;
       return ds ;
    }
    digit digits_next (Digits ds) {
       // Caller should stop the loop when ds->end is true:
       assert (! ds->end) ;
     
       // Step to next digit:
       ds->i -- ;
       uint i = ds->i ;
       ds->low_digit = ! ds->low_digit ;
       digit d ;
     
       // Read proper quartet in proper octet:
       if (ds->low_digit)   d = ds->n.octets[i/2].low ;
       else                 d = ds->n.octets[i/2].high ;
     
       // Possibly set flag end-of-enumeration:
       if (i == 0) ds->end = true ;
     
       return d ;
    }
    Ca s'utilise plus ou moins comme un énumérateur (itérateur) dans un langage de plus haut niveau ; ou plus ressemblant encore, comme pour parcourir une liste chaînée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
       Digits ds = digits_new (n) ;
       while (! ds->end) {
       ...
       }
    Pour faire une opération, je crée les énumérateurs pour les deux opérandes et énumère en //.

    (Si l'énumérateur pouvait renvoyer un pointeur sue le chiffre au lieu de sa valeur, je pourrais énumérer le résultat, aussi, et écrire directement dedans ; mais c'est pas possible car un chiffre est un demi-octet. Donc je fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
          // Compute digit-wise sum, taking care of carry:
         ...
          // Store this digit sum into proper quartet:
          if (low_digit)    sum.octets[i_octet].low    = d ;
          else              sum.octets[i_octet].high   = d ;
    Merci encore,
    denis

  6. #6
    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
    @denispir
    Cette solution des champs de bits est non portable (comme pratiquement tout ce qui concerne les champs de bits) notamment parce que l'ordre des champs de bits n'est pas spécifié dans une unité de stockage

    n1256 :
    6.7.2.1 Structure and union specifiers
    ....
    4 A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or
    some other implementation-defined type.
    ....
    10 An implementation may allocate any addressable storage unit large enough to hold a bitfield.
    If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed
    into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is
    put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields
    within a unit (high-order to low-order or low-order to high-order) is implementation-defined
    . The alignment of
    the addressable storage unit is unspecified.

  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
    1- on ne peut jamais écrire tableau = quelque chose. n2 n'est pas une lvalue (une expression qui désigne un objet)

    2- l'opérateur de cast ne peut s'appliquer qu'à un type scalaire

    3- n2 = *((Natural*)(&n1)) ; cf remarque 1 : n2 est de toute façon un tableau

    4-@Neckara :
    Je ne suis pas sûr de moi mais :
    Natural n2 = n1; Devrait marcher au moment de la déclaration de n2 non?
    Non.

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 15/03/2010, 12h22
  2. Tableau HTML taille fixe
    Par shuyun dans le forum Balisage (X)HTML et validation W3C
    Réponses: 7
    Dernier message: 28/08/2009, 15h35
  3. [HTML] Tableau avec Taille Fixe
    Par jamesleouf dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 21/05/2008, 14h42
  4. afficher descriptifs de tailles différentes dans un tableau de taille fixe
    Par poupouille dans le forum Balisage (X)HTML et validation W3C
    Réponses: 1
    Dernier message: 02/02/2008, 22h27
  5. [Tableau] Avoir des cases de taille FIXE!
    Par fayred dans le forum Mise en page CSS
    Réponses: 5
    Dernier message: 17/07/2007, 11h41

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