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 :

Conversion d'un tableau de uint16_t vers un const int *


Sujet :

C

  1. #1
    Membre à l'essai
    Inscrit en
    Décembre 2009
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 7
    Points : 11
    Points
    11
    Par défaut Conversion d'un tableau de uint16_t vers un const int *
    Bonjour

    J'ai un tableau déclaré:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    uint16_t a[20];
    memset(a,0,20);
    je veux extraire un tableau à partir de la 10éme case de type const int *.
    J'ai essayé avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    const int *b;
    b=(const int *)&a[10];
    Mais ça ne marche pas, j'ai fait l’opération de soustraction mais c'est faux.
    Comment faire?
    Merci!

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    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 012
    Points : 23 136
    Points
    23 136
    Par défaut
    Bonjour,

    Tu as deux solutions :

    - soit tu utilises un const uint16_t * : const uint16_t * ptr = tab + 10.
    - soit tu copies ton tableau de uint16_t dans un tableau de int et tu pourras alors obtenir un const int *.

  3. #3
    Membre éclairé
    Avatar de Kirilenko
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    234
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 234
    Points : 807
    Points
    807
    Par défaut
    Bonsoir,

    Ce que tu cherches à faire est erroné.

    En théorie

    La norme du langage C stipule en effet qu'un objet ne doit avoir sa valeur accédée uniquement par une lvalue qui a un type compatible, qualificateurs et signes omis, avec son type effectif (l'exception étant le type caractère). Dans ton cas, l'objet désigné par la lvalue a[10] est potentiellement accédé par une lvalue qui a le type int, ce qui n'est ni une version qualifiée, signée, non signée du type uint16_t ou un type caractère. Par omission de la description d'un comportement particulier, la norme privilégie donc un comportement indéterminé. Cette règle, communément appelée règle de strict aliasing est citée ci-dessous. On notera que les différences entre les normes sont minimes, et ne concernent que la définition du type référence. En C89, il s'agit du « type déclaré », ce qui n'est pas très clair, notamment dans un cas particulier (voir plus bas).

    Citation Envoyé par C11 (n1570), § 6.5 Expressions
    An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
    — a type compatible with the effective type of the object,
    — a qualified version of a type compatible with the effective type of the object,
    — a type that is the signed or unsigned type corresponding to the effective type of the object,
    — a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
    — an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
    — a character type.
    Le type effectif d'un objet est défini par son type déclaré, excepté pour les objets alloués dynamiquement, qui voient leur type fixé par la dernière lvalue les ayant modifiés. Ce sont des petits détails qui peuvent parfois faire une différence dans le comportement observable du programme. Si ça t'intéresse, j'ai co-écrit un cours de vulgarisation à ce sujet.

    En pratique

    Le principal problème des accès aléatoires de cette manière est qu'ils peuvent conduire à des soucis d'alignement. Par exemple, sur une architecture x86, où chaque type est aligné sur une multiple de sa propre taille, a sera aligné sur une frontière de 2, tandis que b est soumis à un alignement de 4. Donc il est probable que b ne soit pas correctement aligné, si on l'assigne à a[10]. Or, les accès non alignés constituent un thème compliqué dans le monde du matériel. En théorie, sur la plupart des architectures Intel, ils sont autorisés, mais cela est au prix de grosses pertes de performance. En outre, d'autres architectures sont moins laxistes et envoient des exceptions lorsque cela se produit.

    Il y a donc nécessité de changer le type d'une de tes deux variables. La première solution de Neckara est correcte, mais la deuxième conduit à une seconde erreur : il n'y a aucune garantie qu'un entier signé (int) puisse tenir une valeur non signée sur 16 bits, puisque la constante INT_MAX ne doit être supérieure qu'à +32767, ce qui est insuffisant pour stocker des valeurs allant jusqu'à +65535. Si tu n'as pas de contrôle sur tes données, un code pourrait ressembler à :

    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
    // C99
     
    #include <assert.h>
    #include <limits.h>
    #include <stdint.h>
     
    uint16_t a[20];
    int b[10];
     
    for (int i = 0; i < 10; ++i)
    {
        uint16_t v = a[i + 10];
        assert((unsigned int)v < (unsigned int)INT_MAX);
        b[i] = v;
    }
    Chose assez intéressante, gcc (je n'ai que la vieille version 4.4.4 sur ma machine) affiche un avertissement qui me paraît être un faux positif « comparison is always true due to limited range of data type ». Serait-ce un nouveau déboire du typeur non portable imposé par les spécifications du langage C ?

    Bonne soirée !

  4. #4
    Membre à l'essai
    Inscrit en
    Décembre 2009
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 7
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Bonjour,

    Tu as deux solutions :

    - soit tu utilises un const uint16_t * : const uint16_t * ptr = tab + 10.
    - soit tu copies ton tableau de uint16_t dans un tableau de int et tu pourras alors obtenir un const int *.
    Merci pour la réponse.
    j'ai une fonction que je veux utiliser qui prend comme paramètre un const int*.
    Alors il me reste que copier le tableau?

  5. #5
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    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 012
    Points : 23 136
    Points
    23 136
    Par défaut
    Citation Envoyé par gnichiarsenal Voir le message
    Merci pour la réponse.
    j'ai une fonction que je veux utiliser qui prend comme paramètre un const int*.
    Alors il me reste que copier le tableau?
    Oui, tu ne peux pas faire autrement à moins d'utiliser une autre fonction ou de réécrire la fonction que tu souhaite utiliser.

  6. #6
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Citation Envoyé par gnichiarsenal Voir le message
    Bonjour

    J'ai un tableau déclaré:
    uint16_t a[20];
    memset(a,0,20);
    je veux extraire un tableau à partir de la 10éme case de type const int *
    J'ai essayé avec :
    const int *b;
    b=(const int *)&a[10];
    Mais ça ne marche pas, j'ai fait l’opération de soustraction mais c'est faux.
    Comment faire?
    Merci!
    Bonsoir,

    plusieurs remarques :
    • le troisième paramètre de memset est une taille donnée en octets ... 20 uint16_t doivent faire 40 octets ... le memset n'est pas correct, utilise sizeof pour récupérer la bonne taille.
    • uint16_t et int ont-ils la même taille ? je suppose que non mais ça dépend de ta plateforme. Si tu es sous windowx, mac ou linux les int auront au minimum 32 bits alors que les uint16_t font ... 16 bits


    Qu'entends-tu pas opération de soustraction ?????

  7. #7
    Membre à l'essai
    Inscrit en
    Décembre 2009
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 7
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par kwariz Voir le message
    Qu'entends-tu pas opération de soustraction ?????
    Oui j'ai fait a[i+10]-b[i].
    Si je procède bit par bit ça va fonctionner, non?

  8. #8
    Membre à l'essai
    Inscrit en
    Décembre 2009
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 7
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par Kirilenko Voir le message
    Bonsoir,

    Ce que tu cherches à faire est erroné.

    En théorie

    La norme du langage C stipule en effet qu'un objet ne doit avoir sa valeur accédée uniquement par une lvalue qui a un type compatible, qualificateurs et signes omis, avec son type effectif (l'exception étant le type caractère). Dans ton cas, l'objet désigné par la lvalue a[10] est potentiellement accédé par une lvalue qui a le type int, ce qui n'est ni une version qualifiée, signée, non signée du type uint16_t ou un type caractère. Par omission de la description d'un comportement particulier, la norme privilégie donc un comportement indéterminé. Cette règle, communément appelée règle de strict aliasing est citée ci-dessous. On notera que les différences entre les normes sont minimes, et ne concernent que la définition du type référence. En C89, il s'agit du « type déclaré », ce qui n'est pas très clair, notamment dans un cas particulier (voir plus bas).



    Le type effectif d'un objet est défini par son type déclaré, excepté pour les objets alloués dynamiquement, qui voient leur type fixé par la dernière lvalue les ayant modifiés. Ce sont des petits détails qui peuvent parfois faire une différence dans le comportement observable du programme. Si ça t'intéresse, j'ai co-écrit un cours de vulgarisation à ce sujet.



    En pratique

    Le principal problème des accès aléatoires de cette manière est qu'ils peuvent conduire à des soucis d'alignement. Par exemple, sur une architecture x86, où chaque type est aligné sur une multiple de sa propre taille, a sera aligné sur une frontière de 2, tandis que b est soumis à un alignement de 4. Donc il est probable que b ne soit pas correctement aligné, si on l'assigne à a[10]. Or, les accès non alignés constituent un thème compliqué dans le monde du matériel. En théorie, sur la plupart des architectures Intel, ils sont autorisés, mais cela est au prix de grosses pertes de performance. En outre, d'autres architectures sont moins laxistes et envoient des exceptions lorsque cela se produit.

    Il y a donc nécessité de changer le type d'une de tes deux variables. La première solution de Neckara est correcte, mais la deuxième conduit à une seconde erreur : il n'y a aucune garantie qu'un entier signé (int) puisse tenir une valeur non signée sur 16 bits, puisque la constante INT_MAX ne doit être supérieure qu'à +32767, ce qui est insuffisant pour stocker des valeurs allant jusqu'à +65535. Si tu n'as pas de contrôle sur tes données, un code pourrait ressembler à :

    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
    // C99
     
    #include <assert.h>
    #include <limits.h>
    #include <stdint.h>
     
    uint16_t a[20];
    int b[10];
     
    for (int i = 0; i < 10; ++i)
    {
        uint16_t v = a[i + 10];
        assert((unsigned int)v < (unsigned int)INT_MAX);
        b[i] = v;
    }
    Chose assez intéressante, gcc (je n'ai que la vieille version 4.4.4 sur ma machine) affiche un avertissement qui me paraît être un faux positif « comparison is always true due to limited range of data type ». Serait-ce un nouveau déboire du typeur non portable imposé par les spécifications du langage C ?

    Bonne soirée !
    Merci!
    Je ne suis pas un développeur et je suis impressionné par la qualité de vos réponses. Effectivement je veux que mon code serai portable car je vais le compiler après pour ARM. Merci

Discussions similaires

  1. [HTML] conversion d'un tableau html statique vers excel
    Par More dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 21/08/2008, 17h30
  2. Conversion tableau pour exporté vers SQL
    Par badstef dans le forum Macros et VBA Excel
    Réponses: 0
    Dernier message: 29/01/2008, 05h12
  3. Conversion d'un tableau de float en double ?
    Par alex6891 dans le forum C++
    Réponses: 5
    Dernier message: 05/01/2006, 06h04
  4. exporter un tableau de donnée vers un document word
    Par demerzel0 dans le forum Access
    Réponses: 2
    Dernier message: 04/11/2005, 11h57
  5. Réponses: 1
    Dernier message: 30/09/2005, 19h17

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