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 !!!).
"Matt" wrote in message news:<4002454b$0$22324$...
|> >>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.
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.
Quand il s'agit d'écrire un nombre exact d'octets dans un fichier (ou sur le reseau), la meilleur solution reste toujours à écrire tant d'octets, comme des octets. Si on a une chaîne de caractères, par exemple, on pourrait faire quelque chose du genre :
void writeString( ostream& dest, std::string const& source, int count ) { std::string::const_iterator i = source.begin() ; while ( count > 0 ) { dest.put( i == source.end() ? ' ': *i ++ ) ; count -- ; } }
Pour des types autres que les chaînes de caractères, le problème est plus complex, parce que les formats des entiers ne sont pas identiques sur toutes les machines. Dans la pratique, si tu sais que tu n'aurais jamais à porter que sur des machines couramment répandues, tu peux supposer que le format interne est complément à deux, ce qui est aussi le format le plus courant pour des valeurs binaires dans des fichiers ou sur le reseau. (En ce qui concerne les machines plus exotiques, il en existe où même la taille des bytes n'est pas huit bits.) Tu n'aurais donc plus qu'à t'occuper de la taille (combien d'octets) et de l'ordre des octets. Pour un entier de 4 octets, par exemple :
(Cet exemple sort les octets le poids forts d'abord, c-à-d dans l'ordre Internet. On inverse l'ordre des écritures pour les sortir poids faibles d'abord.)
N'oublie pas que dans des cas comme ceci, il faut que le fichier soit ouvert en binaire.
Souvent, on veut formatter tout un enrégistrement en mémoire, afin de pouvoir l'écrire d'un coup. Dans ce cas, on peut très bien se servir d'un vector<char>, en remplaçant les dest.put() par des dest.push_back(). Sinon, formatter vers un char[], au moyen de ostrstream, marche bien aussi ; si tu dois formatter certains champs (par exemple, sortir des nombres en texte), c'est la seule solution valable.
Le seul problème avec cette méthode, c'est qu'il devient rapidement pénible (et une source d'erreurs) de compter tout à la main. C'est en fait bien plus facile à le laisser faire par le compilateur, en écrivant quelque chose du genre :
Selon la norme, rien n'y est garantie. Le compilateur a le droit d'y insérer des octets supplémentaire de rembourrage ou bon lui semble. Dans la pratique, en revanche, j'ai d'assez bonnes expériences avec ça à condition que tous les champs de la struct soit des char[] (et que des char[]). Pour utiliser cette technique, les règles suivantes s'imposent :
- Tout au début du programme, il faut un assert que la taille de la struct est bien celui que tu veux.
- On insère toujours les valeurs comme ci-dessus. Pas de memcpy ou d'autres (au moins qu'on fasse un memcpy d'un champs déjà formatté). Pour les sorties formattées, c'est toujours possible à faire des choses du genre :
C'est une utilisation particulière de strstream ; on ne peut pas la remplacer par stringstream.
Mais dans l'ensemble, la première méthode est plus sûre, même si c'est un peu plus fastidieux à mettre en oeuvre.
-- James Kanze GABI Software mailto: Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
"Matt" <mirabon_nospam@free.fr> wrote in message
news:<4002454b$0$22324$626a54ce@news.free.fr>...
|> >>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.
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.
Quand il s'agit d'écrire un nombre exact d'octets dans un fichier (ou
sur le reseau), la meilleur solution reste toujours à écrire tant
d'octets, comme des octets. Si on a une chaîne de caractères, par
exemple, on pourrait faire quelque chose du genre :
void
writeString( ostream& dest, std::string const& source, int count )
{
std::string::const_iterator
i = source.begin() ;
while ( count > 0 ) {
dest.put( i == source.end() ? ' ': *i ++ ) ;
count -- ;
}
}
Pour des types autres que les chaînes de caractères, le problème est
plus complex, parce que les formats des entiers ne sont pas identiques
sur toutes les machines. Dans la pratique, si tu sais que tu n'aurais
jamais à porter que sur des machines couramment répandues, tu peux
supposer que le format interne est complément à deux, ce qui est aussi
le format le plus courant pour des valeurs binaires dans des fichiers ou
sur le reseau. (En ce qui concerne les machines plus exotiques, il en
existe où même la taille des bytes n'est pas huit bits.) Tu n'aurais
donc plus qu'à t'occuper de la taille (combien d'octets) et de l'ordre
des octets. Pour un entier de 4 octets, par exemple :
(Cet exemple sort les octets le poids forts d'abord, c-à-d dans l'ordre
Internet. On inverse l'ordre des écritures pour les sortir poids faibles
d'abord.)
N'oublie pas que dans des cas comme ceci, il faut que le fichier soit
ouvert en binaire.
Souvent, on veut formatter tout un enrégistrement en mémoire, afin de
pouvoir l'écrire d'un coup. Dans ce cas, on peut très bien se servir
d'un vector<char>, en remplaçant les dest.put() par des
dest.push_back(). Sinon, formatter vers un char[], au moyen de
ostrstream, marche bien aussi ; si tu dois formatter certains champs
(par exemple, sortir des nombres en texte), c'est la seule solution
valable.
Le seul problème avec cette méthode, c'est qu'il devient rapidement
pénible (et une source d'erreurs) de compter tout à la main. C'est en
fait bien plus facile à le laisser faire par le compilateur, en écrivant
quelque chose du genre :
Selon la norme, rien n'y est garantie. Le compilateur a le droit d'y
insérer des octets supplémentaire de rembourrage ou bon lui semble. Dans
la pratique, en revanche, j'ai d'assez bonnes expériences avec ça à
condition que tous les champs de la struct soit des char[] (et que des
char[]). Pour utiliser cette technique, les règles suivantes s'imposent :
- Tout au début du programme, il faut un assert que la taille de la
struct est bien celui que tu veux.
- On insère toujours les valeurs comme ci-dessus. Pas de memcpy ou
d'autres (au moins qu'on fasse un memcpy d'un champs déjà formatté).
Pour les sorties formattées, c'est toujours possible à faire des
choses du genre :
C'est une utilisation particulière de strstream ; on ne peut pas la
remplacer par stringstream.
Mais dans l'ensemble, la première méthode est plus sûre, même si c'est
un peu plus fastidieux à mettre en oeuvre.
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
"Matt" wrote in message news:<4002454b$0$22324$...
|> >>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.
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.
Quand il s'agit d'écrire un nombre exact d'octets dans un fichier (ou sur le reseau), la meilleur solution reste toujours à écrire tant d'octets, comme des octets. Si on a une chaîne de caractères, par exemple, on pourrait faire quelque chose du genre :
void writeString( ostream& dest, std::string const& source, int count ) { std::string::const_iterator i = source.begin() ; while ( count > 0 ) { dest.put( i == source.end() ? ' ': *i ++ ) ; count -- ; } }
Pour des types autres que les chaînes de caractères, le problème est plus complex, parce que les formats des entiers ne sont pas identiques sur toutes les machines. Dans la pratique, si tu sais que tu n'aurais jamais à porter que sur des machines couramment répandues, tu peux supposer que le format interne est complément à deux, ce qui est aussi le format le plus courant pour des valeurs binaires dans des fichiers ou sur le reseau. (En ce qui concerne les machines plus exotiques, il en existe où même la taille des bytes n'est pas huit bits.) Tu n'aurais donc plus qu'à t'occuper de la taille (combien d'octets) et de l'ordre des octets. Pour un entier de 4 octets, par exemple :
(Cet exemple sort les octets le poids forts d'abord, c-à-d dans l'ordre Internet. On inverse l'ordre des écritures pour les sortir poids faibles d'abord.)
N'oublie pas que dans des cas comme ceci, il faut que le fichier soit ouvert en binaire.
Souvent, on veut formatter tout un enrégistrement en mémoire, afin de pouvoir l'écrire d'un coup. Dans ce cas, on peut très bien se servir d'un vector<char>, en remplaçant les dest.put() par des dest.push_back(). Sinon, formatter vers un char[], au moyen de ostrstream, marche bien aussi ; si tu dois formatter certains champs (par exemple, sortir des nombres en texte), c'est la seule solution valable.
Le seul problème avec cette méthode, c'est qu'il devient rapidement pénible (et une source d'erreurs) de compter tout à la main. C'est en fait bien plus facile à le laisser faire par le compilateur, en écrivant quelque chose du genre :
Selon la norme, rien n'y est garantie. Le compilateur a le droit d'y insérer des octets supplémentaire de rembourrage ou bon lui semble. Dans la pratique, en revanche, j'ai d'assez bonnes expériences avec ça à condition que tous les champs de la struct soit des char[] (et que des char[]). Pour utiliser cette technique, les règles suivantes s'imposent :
- Tout au début du programme, il faut un assert que la taille de la struct est bien celui que tu veux.
- On insère toujours les valeurs comme ci-dessus. Pas de memcpy ou d'autres (au moins qu'on fasse un memcpy d'un champs déjà formatté). Pour les sorties formattées, c'est toujours possible à faire des choses du genre :
C'est une utilisation particulière de strstream ; on ne peut pas la remplacer par stringstream.
Mais dans l'ensemble, la première méthode est plus sûre, même si c'est un peu plus fastidieux à mettre en oeuvre.
-- James Kanze GABI Software mailto: Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
konroth
Matt a écrit:
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...
--------------------------------------------------------------------------------------- on peux choisir dans les 'compiler options' les 'struct member alingement'. Visual c++ 6 default c'est huit(8) byte. Ca explique la "fausse" taille.
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...
---------------------------------------------------------------------------------------
on peux choisir dans les 'compiler options' les 'struct member alingement'.
Visual c++ 6 default c'est huit(8) byte. Ca explique la "fausse" taille.
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...
--------------------------------------------------------------------------------------- on peux choisir dans les 'compiler options' les 'struct member alingement'. Visual c++ 6 default c'est huit(8) byte. Ca explique la "fausse" taille.