Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[ANSI C] conversion de type champs de bits vers entier

4 réponses
Avatar
Sam Vimaire
Bonjour..

N'ai-je pas le droit de promouvoir un bitfield déclaré de la façon
suivante :

typedef struct
{
char pipobit1:1
char pipobit2:1

}pipobitfield_t;
pipobitfield_t pipo;

vers un entier 8 bits ?

(char) (pipo)
me génère:
Invalid type Conversion.

Le problème est le même en utilisant le tupe int (ou unsigned int) dans
l'exemple ci dessus ..

Merci de me sortir de ce mauvais pas

4 réponses

Avatar
Antoine Leca
En news:, Sam Vimaire va escriure:
N'ai-je pas le droit de promouvoir un bitfield déclaré de la façon
suivante :
typedef struct {
unsigned pipobit1:1, pipobit2:1;
}pipobitfield_t;
pipobitfield_t pipo;
vers un entier ?
(char) (pipo)


Quel sens donnes-tu à la conversion depuis une paire d'entier (la structure)
vers un entier (le char) ?


Si tu veux faire une conversion binaire vers décimal, il faut passer par les
représentations sous-jacentes, et donc des pointeurs vers des données non
typées. Quelque chose comme

* (unsigned char*) (void*) & pipo

(tu fabriques un pointeur vers tes données binaires, tu enlèves le type,
puis tu expliques qu'en fait il s'agit de données de format char, et tu
récupères la valeur que les données binaires ont quand elles sont
interprétées comme étant un char).


Quant à la conformité ANSI (c'est-à-dire la portabilité) d'une telle
construction, il ne faut pas attendre de miracles. Suivant les machines, tes
deux bits vont être rangés dans l'ordre des poids croissants (gros-boutien)
ou décroissants (petit-boutien) ; de plus, suivant les compilateurs, le
bourrage jusqu'à la taille d'un char va être tantôt à droite, tantôt à
gauche ; il est même possible sur une machine gros-boutienne que tu ne
retrouve pas tes données du tout, si le compilateur aligne la struct sur un
entier.

Par ailleurs, j'ai supprimé toutes les suppositions hors norme que tu avais
faites (utilisation de champs de bits typés char, champs non signés par
défaut, char de 8 bits)


Antoine

Avatar
Sam Vimaire
Antoine Leca a exprimé avec précision :
Quel sens donnes-tu à la conversion depuis une paire d'entier (la structure)
vers un entier (le char) ?
<COUIC>
Si tu veux faire une conversion binaire vers décimal, il faut passer par les
représentations sous-jacentes, et donc des pointeurs vers des données non
typées


Merci pour cette réponse claire.
Plutot que de chercher la petite bête pour une syntaxe j'ai procédé
autrement..

Pour Info voici quel était **grosso modo** le contexte (en reprenant le
code précédant)

- reception d'un octet sur un port série.
- analyse de la valeur de l'octet et mise à 1 des bits de la structure
(pipobit1=1 pipobit2=0 par exemple)
- envoie sur un autre port série d'un octet composé des bits de pipo.
(envoie de l'octet 0x01 dans cette exemple)


Ma procédure d'envoie de l'octet prend un char un argument.
envoieoctet((char) pipo);
d'ou l'erreur


OK
Merci

Avatar
Pierre Maurette

[...]

Pour Info voici quel était **grosso modo** le contexte (en reprenant le code
précédant)

- reception d'un octet sur un port série.
- analyse de la valeur de l'octet et mise à 1 des bits de la structure
(pipobit1=1 pipobit2=0 par exemple)
- envoie sur un autre port série d'un octet composé des bits de pipo.
(envoie de l'octet 0x01 dans cette exemple)


Ma procédure d'envoie de l'octet prend un char un argument.
envoieoctet((char) pipo);
d'ou l'erreur


Bonjour,
Sauf erreur de ma part, le code de votre premier message ne compilait
pas, manquait de la ponctuation (';'). Il me semble avoir lu ici que le
suffixe _t (pipobitfield_t) était réservé, les gurus confirmeront ou
infirmeront s'il y a lieu. Enfin, c'est un peu chercher les ennuis
d'appeler bit1 ce que tout le monde appelle bit0, à moins que pipobit1
et pipobit2 ne désignent vraiment les deuxième et troisième bits.

J'ai remarqué que c'était souvent - souvent, hein, pas toujours - une
mauvaise idée de vouloir considérer des bits comme des bits dans un
programme en C. Le type même de l'optimisation illusoire.

Vous lisez une valeur entière non signée peut-être entre 0 et 255, pour
vous un "octet", c'est à dire quelque chose qui quelque part fait huit
bits et peut s'interprêter bit par bit. La représentation d'un "octet"
en C est un tableau de huit bool ou unsigned réduits à 0 ou 1. Ce
tableau peut avantageusement être remplacé par une structure ou un
bitfield mais sans intérêt majeur à mon sens. J'écris "sans intérêt
majeur" parce que vous ne pouvez pas de façon portable faire des
suppositions sur les représentations mémoire de la donnée et du
bitfield(*). Il vous suffit de remplir le tableau - structure, bitfield
- par le reste des divisions successives par deux.
Et l'inverse avant de livrer l'octet.


(*) Et si vous le faites, l'utilisation du bitfield apporte peu par
rapport à l'entier. Si vous réduisez votre portabilité à la
disponibilité de uint8_t, réduction sur contraignante s'il en est, vous
pouvez faire des trucs comme:

uint8_t MASKEXTRACT[] = {1, 2, 4, 8, 16, 32, 64, 128};
uint8_t MASKFORCE[] = {254, 253, 251, 247, 239, 223, 191, 127};

static inline int GetBit(uint8_t octet, int n){
return !!(octet & MASKEXTRACT[n]);
}

static inline void SetBit(uint8_t* poctet, int n){
*poctet = *poctet | MASKEXTRACT[n];
}

static inline void ResetBit(uint8_t* poctet, int n){
*poctet = *poctet & MASKFORCE[n];
}

--
Pierre Maurette

Avatar
Antoine Leca
En news:, Pierre Maurette va escriure:
Il me semble avoir lu ici que le suffixe _t (pipobitfield_t) était
réservé, les gurus confirmeront ou infirmeront s'il y a lieu.


C'est comme cela dans la norme POSIX (et dérivées), mais ce n'est pas
formellement réservé dans la norme ANSI.

Enfin, c'est un peu chercher les ennuis
d'appeler bit1 ce que tout le monde appelle bit0,


À ce sujet, il me semble que de meilleurs noms seraient ceux du genre
msb{0,1,2...}, ou lsb{0,1,2...}, selon l'idée que l'on a de l'architecture
cible.
Qu'en penses-tu ?


Antoine