OVH Cloud OVH Cloud

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
Régis Troadec
"Emmanuel Delahaye" a écrit dans le message de
news:
In 'fr.comp.lang.c', "Régis Troadec" wrote:

fic); , fic etant un fichier binaire ouvert. Ca sera valide et portable
si CHAR_BIT (nb bits pour type char, dans <limits.h>) vaut 8, ce qui est


La taille interne des char du C n'a aucune importance. Les bytes des flux
font toujours 8 bits (rien à voir avec le C).


Oui, mais si tu fais ceci :
...
unsigned char machin;
...
fread(&machin, sizeof(unsigned char), 1, fichier);
...
et que le char ne soit pas sur 8 bits mais plus, tu vas lire des bits en
trop dans le fichier. La premiere lecture marchera mais un fread()
supplementaire et ce n'est plus valide.

Regis


Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "Régis Troadec" wrote:

La taille interne des char du C n'a aucune importance. Les bytes des flux
font toujours 8 bits (rien à voir avec le C).


Oui, mais si tu fais ceci :
...
unsigned char machin;
...
fread(&machin, sizeof(unsigned char), 1, fichier);
...
et que le char ne soit pas sur 8 bits mais plus, tu vas lire des bits en
trop dans le fichier.


Vu que 'sizeof (unsigned char)' vaut 1 par définition, je ne vois pas
comment.

La premiere lecture marchera mais un fread()
supplementaire et ce n'est plus valide.


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

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?libÉ9
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/


Avatar
Régis Troadec
"Emmanuel Delahaye" a écrit dans le message de
news:

Salut,

In 'fr.comp.lang.c', "Régis Troadec" wrote:

Pas fini : par conséquent, lire le fichier en mettant les valeurs dans
la


structure membre par membre.

BMP_header * st;
FILE * fic;

/* allocs + ouv. fichier */

fread(st->signature, 1, 2, fic);


Non, ça ne résout pas les problèmes d'endianness.


Ben apres il peut toujours utiliser par exemple un tableau d'unsigned char
pour transposer les octets
de ses valeurs lues en fonction de l'endianess du système. C'est peut etre
moins bien qu'une lecture octet pat octet, mais bon, c'est a l'OP de
choisir, question de conception.

Regis


Avatar
Régis Troadec
"Emmanuel Delahaye" a écrit dans le message de
news:
In 'fr.comp.lang.c', "Régis Troadec" wrote:

La taille interne des char du C n'a aucune importance. Les bytes des
flux



font toujours 8 bits (rien à voir avec le C).


Oui, mais si tu fais ceci :
...
unsigned char machin;
...
fread(&machin, sizeof(unsigned char), 1, fichier);
...
et que le char ne soit pas sur 8 bits mais plus, tu vas lire des bits
en


trop dans le fichier.


Vu que 'sizeof (unsigned char)' vaut 1 par définition, je ne vois pas
comment.


Je dois etre fatigue mais c'est interessant. Oui sizeof(char) =1, mais
prenons un (unsigned) char sur par exemple 12 bits,
apres un fread() de 1 char ou un fgetc(), ca va bien pointer un byte soit 12
bits plus loin, non ?


La premiere lecture marchera mais un fread()
supplementaire et ce n'est plus valide.


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


Bon ben je vais me coucher alors. Je veux bien te croire (surement meme pour
plus de 90% des systemes) mais ca me laisse dubitatif.

Regis



Avatar
Marc Boyer
In article <c9o52a$q0a$, Tom wrote:
"Emmanuel Delahaye" a écrit dans le message de
news:

Mauvais design. Une structure C n'est absolument pas faite pour mapper un
flux de bytes (la preuve).


En fait j'effectue une lecture d'un fichier image bitmap. Je commence tout
d'abord par lire l'entête fichier, puis l'entête image, puis la palette et
enfin l'image en elle même.

Je croyais qu'il était plus propre de créer, pour les entête au moins, une
structure :

typedef struct {
unsigned char signature[2];
unsigned long int tailleFic
unsigned long int champsInco
unsigned long int offsetImgFic
} BMP_Header;

et de lire avec un fread(&maStruct,sizeof(BMP_Header),1,fic)


Parce que tu confonds (comme beaucoup de monde) représentation
interne des données et format de stockage.
Ta structure est surement très utile pour manipuler une image,
mais pas pour les E/S de stockage.

Si je comprends bien, il ne me reste qu'à lire octet par octet, et de
convertir mes paquets de 2 en unsigned short et mes paquets de 4 en unsigned
long ?


Parce que tu es sur que sizeof(unsigned short) == 2,
sizeof(unsigned long) == 4 et que le fichier et ton processeurs
ont la même vision gros/petit-boutiste ?

Marc Boyer
--
La contractualisation de la recherche, c'est me donner de l'argent pour
faire ce que je ne sais pas faire, que je fais donc mal, pendant que ce
que je sais faire, je le fais sans moyens...


Avatar
Stephane Legras-Decussy
"Régis Troadec" a écrit dans le message de news:
c9ocef$1ds$
Je dois etre fatigue mais c'est interessant. Oui sizeof(char) =1, mais
prenons un (unsigned) char sur par exemple 12 bits,
apres un fread() de 1 char ou un fgetc(), ca va bien pointer un byte soit
12

bits plus loin, non ?


le C dit que un char fait au moins 8 bits (donc un prog portable ne doit pas
utiliser
les autres bits)...

cela me parait logique que les fonctions portables fputc()/fgetc() ne voient
que les 8 premiers bits des char... non ?

Avatar
Tom
"Régis Troadec" a écrit dans le message de
news:c9o9uv$an4$

Ben apres il peut toujours utiliser par exemple un tableau d'unsigned char
pour transposer les octets
de ses valeurs lues en fonction de l'endianess du système. C'est peut etre
moins bien qu'une lecture octet pat octet, mais bon, c'est a l'OP de
choisir, question de conception.

Regis



Ok.
Voilà qui ne me réjouit pas vraiment : je pensais effectuer une lecture
simple, et je me retrouve avec des discutions sur la taille d'un char (bien
que K&R indiquent char = 1 octet) et en trainant un peu plus sur le net je
tombe sur un conflit entre boutistes et boutiens, erm c'est pas mon jour ^^

En tout cas je fais continuer mon programme en tenant compte de vos
remarques (par exemple je n'ai pas à tenir compte de l'endianness dans mon
cas précisement... à condition que l'endianness des fichiers images soit
toujours la même !)


Tom

Avatar
Vincent Lefevre
Dans l'article <c9po06$i9r$,
Tom écrit:

Voilà qui ne me réjouit pas vraiment : je pensais effectuer une
lecture simple, et je me retrouve avec des discutions sur la taille
d'un char (bien que K&R indiquent char = 1 octet)


Le vrai K&R indique char = 1 byte (en anglais, donc). La traduction
française du K&R est incorrecte, car 1 byte correspond à 1 multiplet
et non pas à 1 octet.

--
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:

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)?

--
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
Alexandre BACQUART
Tom wrote:
Je croyais qu'il était plus propre de créer, pour les entête au moins, une
structure :

typedef struct {
unsigned char signature[2];
unsigned long int tailleFic
unsigned long int champsInco
unsigned long int offsetImgFic
} BMP_Header;

et de lire avec un fread(&maStruct,sizeof(BMP_Header),1,fic)


Bien-sûr ça "paraît" plus propre. C'est même plus lisible et ça marche à
partir du moment où tu n'as pas de pointeurs dans ta structure et que le
fichier que tu crées n'a aucune raison de passer d'une architecture à
l'autre et que tu ne vois aucun inconvénient à stocker des octets
superflus... ça fait beaucoup de contraintes je trouve !

Ton problème est un piège souvent tendu par certaines docs (pas besoin
de chercher très loin d'ailleurs !) cherchant à définir le format d'un
flux avec des structures C, ce qui AMHA est une très mauvaise initiative
(la tentation de faire un copier-coller est forte). 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...), mais l'endianness et le padding, dépendants à la fois de
l'architecture et de l'implémentation, vont se faire une joie de réduire
tes illusions à néant...

Bref, à déconseiller, même si tu es sûr que la non-portabilité de ton
fichier ne pose pas problème, le padding pouvant devenir très gourmand
(plus de place pour moins d'efficacité). Ca reste une mauvaise habitude.
En fait, tu devrais être concerné par chaque octet d'un fichier binaire
que tu crées. Ca impose un peu de gymnastique parfois et il faut
reconnaître que C n'excelle pas particulièrement dans la facilité de
gestion des bases de données.


--
Tek

1 2 3 4