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

Taille d'une structure

12 réponses
Avatar
Matt
Bonjour,

un petit soucis :

#include <iostream>

struct Entete
{
char toto[5];
long tata;
};


int main(void)
{
Entete titi;

std::cout << "Taille d'un long : " << sizeof(long) << std::endl
// Ca me retourne 4 octets : OK
<< "Taille d'un char[5] : " << sizeof(char[5]) << std::endl
// Ca me retourne 5 octets : OK
<< "Taille de la structure : " << sizeof(titi) << std::endl;
// Ca me retourne 12 octets ???

return 0;
}

Pourquoi cette difference de taille et une autre question quand je veux
faire
titi.toto = "tyty";

Il me dit que titi.toto doit etre une l-value ???
pourquoi je ne peux affecter "tyty" a titi.toto ???

Ce que je veux faire c'est une structure contenant le format d'une entete
d'un fichier WAVE
et de pouvoir la modifier par la suite pour la mettre dans une fichier
(logique !!!).

Merci pour vos réponses

Matt...

10 réponses

1 2
Avatar
DomiPi
"Matt" a écrit dans le message de
news:400161dc$0$19274$
Bonjour,

un petit soucis :

#include <iostream>

struct Entete
{
char toto[5];
long tata;
};


int main(void)
{
Entete titi;

std::cout << "Taille d'un long : " << sizeof(long) << std::endl
// Ca me retourne 4 octets : OK
<< "Taille d'un char[5] : " << sizeof(char[5]) << std::endl
// Ca me retourne 5 octets : OK
<< "Taille de la structure : " << sizeof(titi) << std::endl;
// Ca me retourne 12 octets ???


Si tu demandes au compilateur de compacter les structures; tu auras 9 pour
ta stucture. Si non par défaut les struct ne le sont pas, il y a des bytes
non utilisés entre les variables.


return 0;
}

Pourquoi cette difference de taille et une autre question quand je veux
faire
titi.toto = "tyty";


Ca, c'est vouloir changer l'adresse de titi.toto et pas y copier "tyty".
Tu dois utiliser strcpy(titi.toto,"tyty"); titi.toto est un string en C,
c'est pas du C++ !!
Etudies comment traiter les pointeurs en C ainsi que les string ...


Il me dit que titi.toto doit etre une l-value ???
pourquoi je ne peux affecter "tyty" a titi.toto ???


Même réponse ...


Ce que je veux faire c'est une structure contenant le format d'une entete
d'un fichier WAVE
et de pouvoir la modifier par la suite pour la mettre dans une fichier
(logique !!!).

Merci pour vos réponses


Pas de quoi
Dominique


Matt...




Avatar
Fabien LE LEZ
On Sun, 11 Jan 2004 15:46:25 +0100, "Matt"
wrote:

Pourquoi cette difference de taille


Question d'alignement. Sur un processeur 32 bits, les membres d'une
classe sont souvent alignés sur 4 octets, et le compilo rajoute des
"blancs" pour s'en assurer. Ainsi, une classe

struct Entete
{
char toto[5];
long tata;
};

sera considérée par le compilo comme :

struct Entete
{
char toto[5];
char padding [3]; // Membre "bidon", bien sûr inaccessible
long tata;
};

de façon à ce que l'espace mémoire occupé par ta tante commence à un 8
octets (ou un multiple de 4 en tout cas) du début de la classe.

et une autre question quand je veux
faire
titi.toto = "tyty";

Il me dit que titi.toto doit etre une l-value ???


Oui.
Le code suivant :

char txt[]= "tyty";
titi.toto= txt;

est illégal, car tu essaies (en gros) de changer l'adresse du membre
de la classe. C'est comme si tu faisais :

long machin;
titi.tata= &machin;

J'imagine que ce que tu veux, c'est copier les 5 octets "tyty" dans le
membre, ce qui est totalement différent.

Dans un cas "normal", je t'aurais conseillé d'utiliser tout simplement
std::string à la place de char[], et le problème eût été réglé.
Toutefois...

Ce que je veux faire c'est une structure contenant le format d'une entete
d'un fichier WAVE
et de pouvoir la modifier par la suite pour la mettre dans une fichier


... dans ce cas précis, tu n'as pas le choix des armes.
Evidemment, tu pourrais encapsuler tout le bricolage à la Windows dans
une classe qui ferait tout le travail "sale" et dangereux en interne,
mais pour un petit programme dans un cadre éducatif, c'est peut-être
un peu lourd (Mais je ne suis pas catégorique sur ce point). Aussi te
conseillerai-je de jeter un oeuil sur les fonctions strncpy() et
memcpy(), en étudiant bien les différences entre les deux. Et en
n'oubliant pas que quand tu ponds tes propres classes, std::string est
largement plus adapté dans la plupart des cas (Dans les cas restants,
c'est std::vector<char> ;-) ).

Au fait, il me semble qu'on n'emploie le mot "structure" qu'en C. En
C++, "struct" et "class" désignent tous les deux une classe ; la
différence entre les deux est que mettre "struct" à la place de
"class" rend l'héritage et les membres publics par défaut.

--
;-)

http://www.gotw.ca/gotw/063.htm
http://www.gotw.ca/gotw/067.htm#2

Avatar
Fabien LE LEZ
On Sun, 11 Jan 2004 16:27:12 +0100, "DomiPi"
wrote:

Tu dois utiliser strcpy(titi.toto,"tyty");


strncpy, plutôt, puisque la taille du tableau d'arrivée est fixe.
strcpy ne fait pas de contrôle sur la taille du tableau à copier.

--
;-)

http://www.gotw.ca/gotw/063.htm
http://www.gotw.ca/gotw/067.htm#2

Avatar
DINH Viêt Hoà

Si tu demandes au compilateur de compacter les structures; tu auras 9 pour
ta stucture. Si non par défaut les struct ne le sont pas, il y a des bytes
non utilisés entre les variables.


d'une manière générale, c'est une mauvaise méthode que de demander de
compacter les structures. Il vaut mieux faire la différence entre la
représentation en mémoire et la représentation sur fichier.

--
DINH V. Hoa,

etPan! - newsreader, mail user agent -- http://libetpan.sf.net/etpan

Avatar
Guillaume LEMAÎTRE
Fabien LE LEZ wrote:
On Sun, 11 Jan 2004 16:27:12 +0100, "DomiPi"
wrote:


Tu dois utiliser strcpy(titi.toto,"tyty");



strncpy, plutôt, puisque la taille du tableau d'arrivée est fixe.
strcpy ne fait pas de contrôle sur la taille du tableau à copier.



mieux : memcpy, pour éviter de controler sans cesse que dans "tyty" il y
ait un ''


Avatar
Matt
Bonsoir,

Merci pour vos reponses (rapides) ...

Matt...
Avatar
James Kanze
"Matt" writes:

|> un petit soucis :

|> #include <iostream>

|> struct Entete
|> {
|> char toto[5];
|> long tata;
|> };

|> int main(void)
|> {
|> Entete titi;

|> std::cout << "Taille d'un long : " << sizeof(long) << std::endl
|> // Ca me retourne 4 octets : OK
|> << "Taille d'un char[5] : " << sizeof(char[5]) << std::endl
|> // Ca me retourne 5 octets : OK
|> << "Taille de la structure : " << sizeof(titi) << std::endl;
|> // Ca me retourne 12 octets ???

|> return 0;
|> }

|> Pourquoi cette difference de taille

Parce que le compilateur est libre de faire ce qu'il veut, et en
général, ne pas lui permettre d'introduire des octets de
rembourrage donnerait des performances inacceptables. Sur la plupart des
machines, accéder à un long qui n'est pas alignée sur une
adresse multiple de huit, par exemple, exigerait un appel d'une fonction
pour y accéder octet par octet. Même sur un Intel, qui permet de
tels accès, l'accès à une adresse non alignée est nettement
moins rapide.

|> et une autre question quand je veux faire
|> titi.toto = "tyty";

|> Il me dit que titi.toto doit etre une l-value ???

C'est parce que les tableaux de type C (T[]) ne marche pas bien, ni en
C, ni en C++. En C++, on écrite std::string dans ce cas-ci, et ça
marche.

|> pourquoi je ne peux affecter "tyty" a titi.toto ???

Parce que c'est interdit. Un tableau de type C, ce n'est pas un type
comme les autres.

|> Ce que je veux faire c'est une structure contenant le format d'une
|> entete d'un fichier WAVE et de pouvoir la modifier par la suite pour
|> la mettre dans une fichier (logique !!!).

C'est un cas un peu spécial. Si j'ai bien compris, tu veux avoir un
struct qui se plaque sur un tableau de char pour implémenter un
format externs.

Formellement, la norme n'offre aucune solution, et il y a des machines
où c'est carrément impossible, du fait de la façon que
fonctionne le hardware. Mais sur des machines courrantes, tu peux le
faire, à condition que la struct ne contient que des char[]. Donc,
dans ton cas :

struct Entete
{
char toto[ 5 ];
unsigned char tata[ 4 /* ou 8 */ ] ;
} ;

std::vector< char > buffer;
buffer.resize( sizeof( Entete ) ) ;
Entete& entete = &buffer[ 0 ] ;
memcpy( entete.toto, leTotoQuilMeFaut, 5 ) ;
memcpy( entete.tata, leTataQuilMeFaut, 4 ) ;

À condition aussi, bien évidemment, que le format interne
corresponde bien au format externe. Ce qui est rarement le cas.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Avatar
James Kanze
"DomiPi" writes:

|> "Matt" a écrit dans le message de
|> news:400161dc$0$19274$

|> > un petit soucis :

|> > #include <iostream>

|> > struct Entete
|> > {
|> > char toto[5];
|> > long tata;
|> > };

|> > int main(void)
|> > {
|> > Entete titi;
|> >
|> > std::cout << "Taille d'un long : " << sizeof(long) << std::endl
|> > // Ca me retourne 4 octets : OK
|> > << "Taille d'un char[5] : " << sizeof(char[5]) << std::endl
|> > // Ca me retourne 5 octets : OK
|> > << "Taille de la structure : " << sizeof(titi) << std::endl;
|> > // Ca me retourne 12 octets ???

|> Si tu demandes au compilateur de compacter les structures; tu auras
|> 9 pour ta stucture.

C'est bien, mais en général, les compilateurs ne les compactent
pas, et il n'y a pas souvent un moyen à leur démander de le faire.

|> Si non par défaut les struct ne le sont pas, il y a des bytes non
|> utilisés entre les variables.

|> > return 0;
|> > }
|> > Pourquoi cette difference de taille et une autre question quand je
|> > veux faire

|> > titi.toto = "tyty";

|> Ca, c'est vouloir changer l'adresse de titi.toto et pas y copier
|> "tyty". Tu dois utiliser strcpy(titi.toto,"tyty");

Et vive les core dumps.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Avatar
James Kanze
Guillaume LEMAÎTRE writes:

|> Fabien LE LEZ wrote:
|> > On Sun, 11 Jan 2004 16:27:12 +0100, "DomiPi"
|> > wrote:

|> >>Tu dois utiliser strcpy(titi.toto,"tyty");

|> > strncpy, plutôt, puisque la taille du tableau d'arrivée est
|> > fixe. strcpy ne fait pas de contrôle sur la taille du tableau
|> > à copier.

|> mieux : memcpy, pour éviter de controler sans cesse que dans
|> "tyty" il y ait un ''

Et pour accéder au délà de la fin du tableau si la source
contient moins d'octets qu'il n'en faut.

La réponse de Fabien a l'avantage d'être correcte du point de vue
du langage. Reste à voir s'il convient au cahier de charges -- on ne
sait pas encore ce qu'on veut exactement.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Avatar
Matt
|> >>Tu dois utiliser strcpy(titi.toto,"tyty");

|> > strncpy, plutôt, puisque la taille du tableau d'arrivée est
|> > fixe. strcpy ne fait pas de contrôle sur la taille du tableau
|> > à copier.

|> mieux : memcpy, pour éviter de controler sans cesse que dans
|> "tyty" il y ait un ''

Et pour accéder au délà de la fin du tableau si la source
contient moins d'octets qu'il n'en faut.

La réponse de Fabien a l'avantage d'être correcte du point de vue
du langage. Reste à voir s'il convient au cahier de charges -- on ne
sait pas encore ce qu'on veut exactement.



Bonjour,

J'ai retenu la réponse de fabien strncpy qui est très bien.
En fait, ma structure est un format d'entête wave.
Je voulais réserver l'espace nécessaire en début de fichier avant de
mettre les échantillons et enfin rajouter dans l'entête les
renseignements
obtenus a la fin de l'enregistrement...(Taille fichier, taille
échantillons ...)
Puis toujours avec cette structure, récupérer les données pour en
faire une lecture.
Il y a des chaînes de caractères (toujours sur 4 octets),
des long et des short... mais j'ai toujours quelques soucis pour la
taille
de ma structure car elle doit faire une taille (44 octets) et ni plus ni
moins.

Matt...

1 2