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

Taille de structure

40 réponses
Avatar
laurent Coanet
J'ai un petit problème avec la taille des structures contenant des char :

typedef struct {
unsigned char c1;
unsigned char c2;
} MaStruct;

un sizeof(MaStruct) renvoie 4 et non le 2 attentu... ce qui me pose problème
pour lire un fichier dont l'entête commence par des informations codées sur
un octet (et je n'ai évidement pas envie de lire chaque info une à une).

Comment résoudre ou détourner ce problème ?

10 réponses

1 2 3 4
Avatar
Antoine Leca
En , Emmanuel Delahaye va
escriure:
Dans l'autre sens, seuls les 8 bits de poids faible seront écrits
dans le byte du flux.


Je prétends que le programme suivant est strictement conforme (et les
accents manquants sont pour éviter les remarques à ce sujet). Et fonctionne
aussi quand CHAR_BIT dépasse 8.

#include <stdio.h>
#include <limits.h>

int main(void) {
FILE *f = tmpfile();
int c, d;

if( !f ) { perror("tmpfile() d*c*nne"); return 0; }
for( c=0 ; c<1<<CHAR_BIT; ++c ) {
if( fputc(c,f) < 0 ) {
perror("impossible d'ecrire");
printf("On essayait avec %d.n", c);
return 0;
}
}
rewind(f);
for( c=0 ; c<1<<CHAR_BIT; ++c ) {
if( (d = fgetc(f)) == c )
continue;
else if( d < 0 ) {
perror("impossible de lire");
printf("On essayait avec %d.n", c);
} else {
printf("Attendu %d, recu %d.n", c, d);
}
return 0;
}
fclose(f);
return 0;
}

Avatar
Richard Delorme


7.19.2 Streams

[#3] A binary stream is an ordered sequence of characters
that can transparently record internal data. Data read in
from a binary stream shall compare equal to the data that
were earlier written out to that stream, under the same
implementation. [...]



La transparence vaut pour des *caractères* (characters). La valeur max
d'un caractère est 255.


Chapitre et verset ?

characters != char


Selon l'orientation du flux, il s'agit soit de "byte-character" (type
char), soit de wide-character (type wchar_t). L'utilisation des
fonctions fwrite et fread oriente le flux en "byte-character", donc,
dans le cas présent, c'est tout-à-fait lié au type (unsigned) char.

--
Richard


Avatar
Alexandre BACQUART
Emmanuel Delahaye wrote:
In 'fr.comp.lang.c', Alexandre BACQUART wrote:


Non seulement un int
(voire un char) n'a pas forcément la même taille d'une architecture à
l'autre (problème cependant facilement résolvable en C99 avec
int8_t...),



C'est pas vrai. Le langage C99 n'a pas le pouvoir de créer des types nouveaux
sur des architectures qui ne peuvent pas les implémenter (Sur un DSP
TMS320C64, il *n'existe pas* d'objets < 16 bits). Dans sa grande sagesse (et
celle des rédacteurs), le langage C99 *n'impose pas* les types à taille fixe.


Bonne précision. Seulement quand ils sont là, tu ne vas quand-même pas
dire que leur taille, à eux, n'est pas garantie, non ?! Et ça devrait
quand-même pas mal limiter les dégâts de les utiliser... si tu as une
meilleure solution, je suis tout ouïe :)

Il dit simplement que *sur les architectures qui l'acceptent*, l'implémenteur
a le droit de définir des types à taille fixe. Ces types sont donc par nature
non portables (leur existence même dépend de l'architecture), et pour moi,
n'ont *aucun* intéret.


Ne suis-je pas en droit de me demander à quoi pense Yoda lorsqu'il
rajoute des bidules sans intérêt dans la norme ?

Au moins, un char, c'est un char, et je me f*us pas mal qu'il fasse 8 ou 128
bits.


Mouais, enfin CHAR_BIT=8, ça me laisserait pas indifférent quand-même
:) Mais je suis ton raisonnement.



--
Tek


Avatar
Vincent Lefevre
Dans l'article ,
Emmanuel Delahaye écrit:

In 'fr.comp.lang.c', Vincent Lefevre <vincent+ wrote:

Non, aucun risque. Le mécanisme interne de lecture de flux est sur 8
bits quoiqu'il arrive.


Ce n'est pas dépendant de l'implémentation (même si en pratique,
c'est actuellement toujours 8 bits)?


En tout cas, seuls les 8 bits de poids faibles sont pris en compte.


Mais tu te bases sur quoi pour dire cela? Sur ton implémentation?
Sur la norme?

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% validated (X)HTML - Acorn / RISC OS / ARM, free software, YP17,
Championnat International des Jeux Mathématiques et Logiques, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA



Avatar
Vincent Lefevre
Dans l'article ,
Emmanuel Delahaye écrit:

C'est pas vrai. Le langage C99 n'a pas le pouvoir de créer des types
nouveaux sur des architectures qui ne peuvent pas les implémenter
(Sur un DSP TMS320C64, il *n'existe pas* d'objets < 16 bits). Dans
sa grande sagesse (et celle des rédacteurs), le langage C99
*n'impose pas* les types à taille fixe. Il dit simplement que *sur
les architectures qui l'acceptent*, l'implémenteur a le droit de
définir des types à taille fixe. Ces types sont donc par nature non
portables (leur existence même dépend de l'architecture), et pour
moi, n'ont *aucun* intéret.


Oui, pour toi.

Les types 'at_least' (int_least<bits>_t) me paraissent plus
intelligents, mais ils n'apportent rien sur le plan sémantique par
rapport aux types existants (à part pour les grands entiers, 64 ou
128 bits). Tout programmeur C muni d'un cerveau en état de marche
sait qu'un char est un 'at_least8', un short et un int un
'at_least16' et un long un 'at_least32'.


Il me semble que la norme n'impose ça nulle part. Tu peux très bien
avoir un char sur 16 bits et un at_least8 sur 8 bits, par exemple.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% validated (X)HTML - Acorn / RISC OS / ARM, free software, YP17,
Championnat International des Jeux Mathématiques et Logiques, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

Avatar
Wallace
Vincent Lefevre n'a pas hésité à écrire...
<news:20040605100921$
Dans l'article ,
Emmanuel Delahaye écrit:

C'est pas vrai. Le langage C99 n'a pas le pouvoir de créer des types
nouveaux sur des architectures qui ne peuvent pas les implémenter
(Sur un DSP TMS320C64, il *n'existe pas* d'objets < 16 bits). Dans
sa grande sagesse (et celle des rédacteurs), le langage C99
*n'impose pas* les types à taille fixe. Il dit simplement que *sur
les architectures qui l'acceptent*, l'implémenteur a le droit de
définir des types à taille fixe. Ces types sont donc par nature non
portables (leur existence même dépend de l'architecture), et pour
moi, n'ont *aucun* intéret.
Oui, pour toi.



<SimpleQuestion mode="Pas taper, merci">
Quel intérêt y voyez-vous si l'existence de ces types n'est pas imposée ?
À part faire du C non portable ?
(Pour ça, il suffisait d'utiliser conio.h, fork(...), et leurs copains...)
</SimpleQuestion>

Les types 'at_least' (int_least<bits>_t) me paraissent plus
intelligents, mais ils n'apportent rien sur le plan sémantique par
rapport aux types existants (à part pour les grands entiers, 64 ou
128 bits). Tout programmeur C muni d'un cerveau en état de marche
sait qu'un char est un 'at_least8', un short et un int un
'at_least16' et un long un 'at_least32'.
Il me semble que la norme n'impose ça nulle part. Tu peux très bien

avoir un char sur 16 bits et un at_least8 sur 8 bits, par exemple.


Certes, mais cela n'enlève rien au fait que les précautions d'emploi d'un
'at_least8' sont les mêmes que pour un 'char', leurs plages valides
(=normatives) de représentation étant les mêmes. À moins que je ne me trompe
?
De fait, le type char peut très bien être le type qui sera utilisé pour être
le at_least8. Personnellement, j'imagine mal des gens qui se casseraient les
pieds à créer un nouveau type s'ils peuvent se baser sur l'existant, mais ma
paresse n'a rien de généralisable...

Tiens, pendant qu'on y est... Si on a un char sur 16 bits et un at_least8
sur 8 bits, les sizeof de ces deux types sont 1 ? Excusez le petit rigolo
que je suis, mais, dans l'affirmative, que définit sizeof, exactement ?
Merci.


-- W.
Pour m'insulter, merci d'enlever vos_fringues.


Avatar
Alexandre BACQUART
Wallace wrote:

Quel intérêt y voyez-vous si l'existence de ces types n'est pas imposée ?


Elle est imposée si c'est disponible.

À part faire du C non portable ?


Portable à 99%. Mais c'est tout relatif. Lorsque tu fais un algo dont
l'efficacité repose essentiellement sur des propriétés courantes des
entiers de X bits (des UB pour la norme), tu fais du nettement moins que
100%, alors 99% c'est convenable.

Après c'est question de goût aussi. Personellement, j'ai toujours défini
mes propres entiers X bits car j'aime connaître la taille réelle des
entiers que je manipule juste en lisant le nom du type. Un héritage de
mes années d'assembleur peut-être...


--
Tek

Avatar
Vincent Lefevre
Dans l'article <40c1a1a4$0$7950$,
Wallace écrit:

Quel intérêt y voyez-vous si l'existence de ces types n'est pas imposée ?


C'est très utile dans certaines applications. Évidemment, on pourrait
s'en sortir avec des types int_least et des masques, avec le risque
d'ajouter des bugs.

À part faire du C non portable ?


Le pourcentage de portabilité est très élevé. D'autre part, la
portabilité peut être limitée par autre chose (d'autres outils
nécessaires...). Le compromis est vite vu.

(Pour ça, il suffisait d'utiliser conio.h, fork(...), et leurs copains...)


conio.h n'existe pas. Concernant fork, je l'utilise souvent (mais pas
en C, je préfère Perl à ce niveau), parce que je ne peux pas faire
autrement.

Il me semble que la norme n'impose ça nulle part. Tu peux très bien
avoir un char sur 16 bits et un at_least8 sur 8 bits, par exemple.


Certes, mais cela n'enlève rien au fait que les précautions d'emploi
d'un 'at_least8' sont les mêmes que pour un 'char', leurs plages
valides (=normatives) de représentation étant les mêmes.


Oui, mais on a plus de chance d'avoir int_least8_t plus petit que char
que l'inverse. De même, je suppose que int_least16_t fera généralement
16 bits exactement sur la plupart des implémentations, alors qu'un int
fera en général au moins 32 bits, même si la norme autorise qu'un int
fasse seulement 16 bits. Les types int_least auront tendance à être
aussi courts que possible, car ils ne sont pollués ni par du code
existant (qu'on ne risque pas de casser), ni par leur utilisation
dans des prototypes de fonctions de la bibliothèque standard.

Tiens, pendant qu'on y est... Si on a un char sur 16 bits et un
at_least8 sur 8 bits, les sizeof de ces deux types sont 1 ?


C'est vrai que cet exemple-là était un peu idiot (enfin, peut-être pas
sur certaines archi avec des vecteurs de mots de 8 bits, si ça existe).

Excusez le petit rigolo que je suis, mais, dans l'affirmative, que
définit sizeof, exactement ?


La taille en char (bits de padding compris). Ici, un int_least8_t
pourrait avoir des bits de padding (pas vérifié si c'est autorisé,
mais bon...).

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% validated (X)HTML - Acorn / RISC OS / ARM, free software, YP17,
Championnat International des Jeux Mathématiques et Logiques, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA


Avatar
Antoine Leca
En 40c1a1a4$0$7950$, Wallace va escriure:
Vincent Lefevre n'a pas hésité à écrire...
<news:20040605100921$

Dans l'article ,
Emmanuel Delahaye écrit:

Il dit simplement que *sur
les architectures qui l'acceptent*, l'implémenteur a le droit de
définir des types à taille fixe. Ces types sont donc par nature non
portables (leur existence même dépend de l'architecture), et pour
moi, n'ont *aucun* intéret.
Oui, pour toi.



<SimpleQuestion mode="Pas taper, merci">
Quel intérêt y voyez-vous si l'existence de ces types n'est pas
imposée ? À part faire du C non portable ?


À partir du moment où la très grande majorité du C qui s'écrit réellement
n'est pas "totalement portable", et quand en plus 99,99% des architectures
actuelles (en code utilisé, pas en nombre brut) sont fondées sur l'adressage
8 bits et donc doivent avoir les dits types, on peux y voir deux intérêts:
- au sein de cet ensemble, ces types SONT portables
- si cette mayonnaise prend, une prochaine révision de la norme, ou un
sous-ensemble normatif, pourrait décider de se restreindre à ces
architectures; et alors ces types-là deviendront totalement portables (et ne
me dites pas que cela n'a aucun sens: Posix:2001 a fait *exactement* ce
chemin-là).


(Pour ça, il suffisait d'utiliser conio.h, fork(...), et leurs
copains...) </SimpleQuestion>


<conio.h> marche très mal sur un terminal ligne, une imprimante ou une
interface graphique à polices proportionelles (par opposition à un écran
adressable par ligne et colonne), sans même aller chercher un terminal
Braille.

fork() marche très mal sur les systèmes qui n'autorisent pas (ou mal) la
duplication des espaces d'adressages. Et là où c'est plus grave, c'est qu'il
y a effectivement des algorithmes où fork() est efficace; mais il y en a
d'autres où fork() est utilisé, alors que ce n'est pas la solution la plus
efficace; résultat, des portages de ces derniers vont subir une double
pénalité: une pour ne pas utiliser l'algorithme efficace, et une autre pour
devoir émuler fork() sur un système qui ne lui est pas favorable.

Il y a une différence importante entre 99,99% et 80%. Même si les deux sont
majoritaires. C'est tout le sens du discours sur l'idéologie dominante !


Tout programmeur C muni d'un cerveau en état de marche
sait qu'un char est un 'at_least8', un short et un int un
'at_least16' et un long un 'at_least32'.
Il me semble que la norme n'impose ça nulle part. Tu peux très bien

avoir un char sur 16 bits et un at_least8 sur 8 bits, par exemple.



C'est possible, mais j'ai peur que ce soit TRÈS difficile à utiliser en
pratique. Par exemple, regarde à quoi ressemble un int_atleast8_t* convertit
en char*.


Certes, mais cela n'enlève rien au fait que les précautions d'emploi
d'un 'at_least8' sont les mêmes que pour un 'char', leurs plages
valides (=normatives) de représentation étant les mêmes. À moins que
je ne me trompe ?


J'ai peur que tu ne te trompes. Je ne pense pas que (int_atleast8_t)'a' soit
strictement conforme (en admettant que int_atleast8_t le soit).


Tiens, pendant qu'on y est... Si on a un char sur 16 bits et un
at_least8 sur 8 bits, les sizeof de ces deux types sont 1 ? Excusez
le petit rigolo que je suis, mais, dans l'affirmative, que définit
sizeof, exactement ? Merci.


La taille en multiplet (l'unité étant le char).

Le fait qu'un type ait X pour sizeof ne signifie pas qu'il soit capable de
stocker toutes les valeurs de 0 à (1<<(X*CHAR_BIT))-1.


Antoine



Avatar
Antoine Leca
En , Emmanuel Delahaye va
escriure:

7.19.2 Streams

[#3] A binary stream is an ordered sequence of characters
that can transparently record internal data. Data read in
from a binary stream shall compare equal to the data that
were earlier written out to that stream, under the same
implementation. [...]


Non. La transparence vaut pour des *caractères* (characters). La
valeur max d'un caractère est 255.


Non. La valeur min du plus grand caractère est 127. Mais je n'ai pas vu de
max.

D'autre part, la définition de printf("%c"...) permet n'importe quelle
valeur sans limitation.


characters != char


Oui, non, c'est selon. En l'occurence, cela ne t'amène rien, parce que la
définition des caractères (ici, éléments du jeu) n'impose aucune limite sur
les valeurs.


Antoine


1 2 3 4