OVH Cloud OVH Cloud

Les structures à taille variables sont elles portables ?

27 réponses
Avatar
Luc de Bauprois
Bonjour

Le code suivant est il portable :

-----------------------------------------------------------------------
struc machin
{
// Autres memebre virés pour plus de clarté

char string[1]; // dernier membre de la struct
};

puis faire des allocation du style

struct machin *s = (struct machin *)malloc( sizeof( struct machin) +
strlen(chaine));

.../...

strcpy( s->chaine, chaine );
-----------------------------------------------------------------------

Ca alloue des struct de taille variable, en laissant de la place "à la
fin" pour écrire le contenu dans la châine.

Est ce "propre" ? Normalisé ? Portable ? Ou y a t'il des effets de bord
pervers qui vont provoquer un merdier indemerdable plus tard ?

Merci

10 réponses

1 2 3
Avatar
espie
In article ,
Luc de Bauprois wrote:
Bonjour

Le code suivant est il portable :

-----------------------------------------------------------------------
struc machin
{
// Autres memebre virés pour plus de clarté

char string[1]; // dernier membre de la struct
};

puis faire des allocation du style

struct machin *s = (struct machin *)malloc( sizeof( struct machin) +
strlen(chaine));

.../...

strcpy( s->chaine, chaine );
-----------------------------------------------------------------------

Ca alloue des struct de taille variable, en laissant de la place "à la
fin" pour écrire le contenu dans la châine.

Est ce "propre" ? Normalisé ? Portable ? Ou y a t'il des effets de bord
pervers qui vont provoquer un merdier indemerdable plus tard ?


C'est propre, normalise, et portable.

Avatar
Jean-Marc Bourguet
Luc de Bauprois writes:

Est ce "propre" ? Normalisé ? Portable ? Ou y a t'il des effets de bord
pervers qui vont provoquer un merdier indemerdable plus tard ?


À ma connaissance, c'est du comportement indéfini, en C90 comme en C99. Ça
ne m'étonnerait pas qu'en pratique ça marche bien car la technique est
répandue. Au point qu'enn C99, elle est autorisée avec une syntaxe
légèrement différente (pour aider une recherche éventuelle: flexible array
member)

struct machin
{
char string[];
};

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Jean-Marc Bourguet
(Marc Espie) writes:

Est ce "propre" ? Normalisé ? Portable ? Ou y a t'il des effets de bord
pervers qui vont provoquer un merdier indemerdable plus tard ?


C'est propre, normalise, et portable.


Référence? Pourquoi alors a-t'on introduit les flexible array members?

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Harpo
Jean-Marc Bourguet wrote:

C'est propre, normalise, et portable.


Référence? Pourquoi alors a-t'on introduit les flexible array
members?


Je crois que les champs d'un struct sont alloués dans l'ordre dans
lequel ils sont définis, dans ce cas je ne vois pas où serait le
problème.

--
http://patrick.davalan.free.fr/


Avatar
Eric Levenez
Le 4/11/06 13:41, dans , « Jean-Marc
Bourguet » a écrit :

(Marc Espie) writes:

Est ce "propre" ? Normalisé ? Portable ? Ou y a t'il des effets de bord
pervers qui vont provoquer un merdier indemerdable plus tard ?


C'est propre, normalise, et portable.


Référence? Pourquoi alors a-t'on introduit les flexible array members?


Parce que c'est une écriture plus propre que de mettre un tableau de 1
élément. Pour calculer la taille de l'en-tête il fallait faire un sizeof
moins 1.

--
Éric Lévénez -- <http://www.levenez.com/>
Unix is not only an OS, it's a way of life.



Avatar
Jean-Marc Bourguet
Harpo writes:

Jean-Marc Bourguet wrote:

C'est propre, normalise, et portable.


Référence? Pourquoi alors a-t'on introduit les flexible array
members?


Je crois que les champs d'un struct sont alloués dans l'ordre dans
lequel ils sont définis, dans ce cas je ne vois pas où serait le
problème.


Si le comportement est formellement indéfini -- ce que j'ai pas cherché à
vérifier, mais à lire un thread récent sur comp.std.c sur quelque chose qui
me semblerait encore plus vraissemblable me semble fortement probable -- et
que quand les optimiseurs se mettent à utiliser le fait qu'un comportement
est indéfini, il est extrêmenent difficile de savoir comment ils peuvent
transformer des choses.

Dans le cas présent, ils pourraient par exemple utiliser un mode
d'adressage capable d'adresser la taille déclarée du tableau mais pas
plus, ou plus vraissemblablement capable d'adresser plus que la taille
déclarée mais pas autant que ce que le programmeur utilise. Un essai avec
des petites valeurs fonctionnerait, avec des valeurs plus grandes pas
correctement, on réutiliserait les premiers éléments par exemple.

Maintenant vu que c'est une pratique relativement courante, il est possible
que les compilateurs fassent un effort raisonnable pour ne pas la casser,
sans toute fois définir officiellement le comportement.

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
Laurent Deniau
Jean-Marc Bourguet wrote:
Luc de Bauprois writes:


Est ce "propre" ? Normalisé ? Portable ? Ou y a t'il des effets de bord
pervers qui vont provoquer un merdier indemerdable plus tard ?



À ma connaissance, c'est du comportement indéfini, en C90 comme en C99.


Absolument.

Ça
ne m'étonnerait pas qu'en pratique ça marche bien car la technique est
répandue.


Jamais eu de probleme avec, c'est un cas de comportement indefini plus
portable que certains comportements definis ;-)

extrait de OOC:

struct T {
const size_t cnt; /* read-only field */
#if OOC_ISO_C < OOC_ISO_C99
array_T data[1]; /* public field, undefined behavior, but... */
#else
array_T data[]; /* public field, defined behavior */
#endif
};

Au point qu'enn C99, elle est autorisée avec une syntaxe
légèrement différente (pour aider une recherche éventuelle: flexible array
member)

struct machin
{
char string[];
};


a+, ld.


Avatar
Jean-Marc Bourguet
Laurent Deniau writes:

Jean-Marc Bourguet wrote:
Luc de Bauprois writes:

Est ce "propre" ? Normalisé ? Portable ? Ou y a t'il des effets de bord
pervers qui vont provoquer un merdier indemerdable plus tard ?
À ma connaissance, c'est du comportement indéfini, en C90 comme en C99.



Absolument.

Ça
ne m'étonnerait pas qu'en pratique ça marche bien car la technique est
répandue.


Jamais eu de probleme avec, c'est un cas de comportement indefini plus
portable que certains comportements definis ;-)

extrait de OOC:

struct T {
const size_t cnt; /* read-only field */


C'est du C ca? Comment initialise-t'on cnt ?

#if OOC_ISO_C < OOC_ISO_C99
array_T data[1]; /* public field, undefined behavior, but... */
#else
array_T data[]; /* public field, defined behavior */
#endif
};


Si tu testes specifiquement pour gcc, il a une extension autorisant
data[0].

Au fait, est-ce qu'il y a quelque chose de public sur OOC? La
derniere fois que j'ai regarde, ta page n'avait que des choses sur
OOPC.

A+

--
Jean-Marc



Avatar
Laurent Deniau
Jean-Marc Bourguet wrote:
Laurent Deniau writes:


Jean-Marc Bourguet wrote:

Luc de Bauprois writes:


Est ce "propre" ? Normalisé ? Portable ? Ou y a t'il des effets de bord
pervers qui vont provoquer un merdier indemerdable plus tard ?


À ma connaissance, c'est du comportement indéfini, en C90 comme en C99.


Absolument.


Ça
ne m'étonnerait pas qu'en pratique ça marche bien car la technique est
répandue.


Jamais eu de probleme avec, c'est un cas de comportement indefini plus
portable que certains comportements definis ;-)

extrait de OOC:

struct T {
const size_t cnt; /* read-only field */



C'est du C ca? Comment initialise-t'on cnt ?


Oui et non ;-) Cette structure n'est definie que dans l'interface.
L'implementation utilise une structure 'generique' unique ou le const
disparait:

struct T {
size_t cnt;
};

Elle est donc la seule a pouvoir le modifier. Ca protege contre une
ingerence 'involontaire' des utilisateurs.

#if OOC_ISO_C < OOC_ISO_C99
array_T data[1]; /* public field, undefined behavior, but... */
#else
array_T data[]; /* public field, defined behavior */
#endif
};



Si tu testes specifiquement pour gcc, il a une extension autorisant
data[0].


Yep. Mais je ne suis pas specifique gcc.

Au fait, est-ce qu'il y a quelque chose de public sur OOC?


Non. Je n'ai jamais fini de le 'nettoyer'. Je peux mettre un tarball sur
le web du code qui compile. Les modules (Unitest, ODBC, etc...) n'ont
jamais ete mis a jour sur la derniere version et depuis je suis passe a
COS ou je suis entrain de finalise le core. Ensuite je migrerais pas mal
de code de OOC vers COS.

La
derniere fois que j'ai regarde, ta page n'avait que des choses sur
OOPC.


Yep. Parce que ecrire de la doc prend plus de temps que d'ecrire du code
;-)

a+, ld.




Avatar
Harpo
Laurent Deniau wrote:

Yep. Parce que ecrire de la doc prend plus de temps que d'ecrire du
code


Hé oui !

;-)


Et ça vous fait rire !

--
http://patrick.davalan.free.fr/

1 2 3