CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[C] flexible array length

Fvirtman
Fvirtman
Niveau 10
04 décembre 2007 à 11:00:16

Pour ne pas pourir le topic "programmation DS" de Isukthar, je crée un autre topic.

Je voulais réagir sur ce qu´a écrit Kufa sur les flexible array length, et tout ce dont tu as parlé.

Je viens de faire quelques tests, (je ne me servais jamais de ça), perso il y a quelque chose qui m´échappe :
Voila ce que j´ai testé

struct Foo{
int a;
int b[];
};

struct Foo foo0 = { 55, {6} };
int i1 = sizeof(foo0);
struct Foo foo1 = { 55, {6, 8, 10} };
int i2 = sizeof(foo1);

Alors Visual C++ 2005 me refuse le b[] en C et en C++ (peut etre pas encore C99 ?) sauf si j´active "langage extentions", a ce moment la, il ne bronche pas. par contre, il compile en C et C++.
Bon, tu vas me dire, Visual peut etre "permissif" si on lui demande. (je ne lance pas de débat visual VS gcc foireux)

Bref, finalement, j´arrive donc quand meme a y compiler.
Ma question, c´est que i1 et i2 me renvoient 4.
Donc finalement, il ne prend comem size de la structure que le int a. Et pourtant si je debug, je vois mon tableau, comme je l´ai rempli : un int, suivi d´un pointeur vers le tableau b.

Donc pourquoi ma sizeof me renvoie 4 ? Je m´attendais a 8 ! la taille de a et celle d´un pointeur vers un tableau. Pourquoi je n´ai que 4 ?

Sinon, mis a part ça, si je comprends bien, ce code est cencé marché en C et non en C++ ? ou l´inverse ?
Car pour moi, on a du code implicite : une allocation dynamique de b, et une destruction implicite aussi. C´est contraire a la philosophie C ou tout est explicite.

J´avais déja vu, sinon, des exemples genre :

void fonc(int n)
{
int tab[n];

}

qui finalement masquent une allocation dynamique en interne (et qui sont moyennement portables). Perso, je n´aime pas bien cela, car c´est trompeur : on y écrit comme un tableau statique, mais en interne, c´est un tableau dynamique...

Bref bref,
pour le moment, ma question, c´est : pourquoi ce sizeof me renvoie 4 ?

godrik
godrik
Niveau 30
04 décembre 2007 à 11:21:01

Je ne sais pas pour la premiere partie. Par contre je voudrais revenir sur le:
void fonc(int n)
{
int tab[n];

}
Le tableau tab n´est pas dynamique, il est alloué sur la pile.

kufa
kufa
Niveau 9
04 décembre 2007 à 11:27:05

Le flexible array length est du C99, donc oui il faut activer les extentions sous visual.
Alors pourquoi le sizeof te renvoie 4? Tout simplement car la norme definie que la taille d un flexible array length(FAV) est volontairement undefined, car une implementation du compilo peut aligner differement le FAV selon sa taille. Donc sizeof(struct_avec_fav)==sizeof(struct_sans_fav)
Les FAV existent seulement en C99.

Le int tab[n] dans une fonction c´est autre chose, ca s´appelle variable-length arrays, et c´est aussi du C99. L´avantage: c´est une allocation sur la stack, ca evite d´avoir avoir recour a (_)alloca (si le compilo le supporte) si on veut garder ca sur la stack en c++. On pourrait tres bien allouer le tableau avec un new/malloc me diras-tu, oui mais non, par exemple lorsqu on code pour du multithreade on veut eviter les possibles contentions que malloc/(custom)new peuvent entrainer. C´est bcp plus portable que alloca (et la duree de vie est le scope, contrairement a alloca ou c´est la fonction pour la plupart des implementations).

/k

Fvirtman
Fvirtman
Niveau 10
04 décembre 2007 à 11:29:10

godrik >
ok, c´est vrai que dans ce cas, quand on rentre dans la fonction, on connaitra la taille lors de l´empilage
par contre, un truc comme

void fonc()
{
int a = 15;
int tab[a];
}

ne doit pas marcher. En fait, il faut que la taille soit calculable avec les parametres.

Mais j´ai vu qu´un truc comme ça marchait :

void fonc(char* a,char* b)
{
int tab[strlen(a)+strlen(b)+1];
}

inattendu, mais finalement par d´inconnus lors de l´empilage. Du coup, les strlen sont appelés avant l´empilage normalement !

Sinon, pour le premier probleme, entre temps, j´ai testé un truc :

struct Foo{
int b[];
int a;
};

Ne compile pas : j´en conclus (peut etre hativement) que le tableau de taille indéfini est une forme de ... de stdarg, et donc doit etre placé a la fin, et que les données du tableau sont de l´override : juste apres la structure. Et donc non englobés par le sizeof. Je trouve ça dangereux si c´est le cas !

Quelqu´un pour confirmer ou démentir ?

Fvirtman
Fvirtman
Niveau 10
04 décembre 2007 à 11:33:16

vrai pour le int tab[n], ça a son avantage.
C´est vrai que j´utilise plutot des std::vector si j´ai vraiment besoin de ça, ou alors il y a boost::array.

Au niveau langage (car le topic a été lancé suite a ta réaction C VS C++), qu´en est il des variable-length arrays ?

int fonc(int n)
{
int tab[n];
}

C ? C++ ? Les deux ?

kufa
kufa
Niveau 9
04 décembre 2007 à 11:44:16

C ? C++ ? Les deux ?

C99 :)

Les VLA sont surtout utiles lorsqu on veut plus de performances.
Et oui les FAV doivent etre le dernier membre, vu qu ils ont une taille indefinie. Il ne faut pas voir ca comme un override (meme si tu peux clairement lire qqchose d invalide si tu n´y fais pas attention), mais ca remplace juste pleins de casts/utilisation d une autre structure/pointeur.
Exemple:
struct Picture { uint32_t m_iWidth; uint32_t m_iHeight; uint32_t pixels[]; };
Il y aura donc un seul bloc memoire pour la def + pixels en C99 (faut se faire chier a l alloc, mais bon a la lecture/utilisation ulterieure c est bcp plus facile), alors qu en c++ on aurait plutot un truc du style:
struct Picture { uint32_t m_iWidth; uint32_t m_iHeight; uint32_t* pixels; Picture(uint32_t,uint32_t); ~Picture(); };
C´est aussi utile pour les structures du style:
struct CallbackParameters { uint32_t type; uint32_t values[]; }; // le nombre de values depends du type

Fvirtman
Fvirtman
Niveau 10
04 décembre 2007 à 11:58:05

C´est vrai que ça a une bonne utilité ! :)
Tu me dis qu´il ne faut pas y voir comme un override. Moi ce qui me gene, c´est que tu ne sais pas exactement comment sont rangées les données du coup ! (meme si j´imagine qu´en pratique, c´est rangé juste apres)
alors que quand tu as plusieurs classes en C++, et quelques heritages virtuels (je pense a l´héritage virtuel en diamant par exemple), ton instance de classe fille gonfle de 1 ou plusieurs sizeof(pointeur) pour lier directement la "grand mere", donc les pointeurs vers le "reste de la mémoire" sont la.
Tandis que dans les FAV, ce pointeur est inexistant, bon, meme si j´imagine que dans la pratique les données sont placées apres.

Mais alors du coup, ça souleve des questions :
Si tu fais un tableau de struct :

struct foo[10];

En toute logique, le sizeof sera 4*10 = 40, alors que, si chaque structure est suivie d´autres données, la taille réelle sera plus grande. Faudra que j´essaie de dumper ça a coup de char*

struct Foo foo = ....
char* c = (char*)&foo;

Sinon, autre question (oui, j´aime les mécanismes internes)
Dans mon 1er topic, j´instancie 2 structures :

une ou je mets 1 element dans le tableau b, l´autre 3.
Est ce que je peux récupérer la taille des tableaux par la suite, ou alors il faut que je la stocke (par exemple dans a)

je me sers souvent de l´astuce suivante :

int tab[] = {1,3,4,5,6};
int n = sizeof(tab)/sizeof(int);

pour récupérer la taille

par contre, la visiblement :
sizeof(foo.b)
il n´aime pas trop !

Il faut que je stocke la taille a coté ? :)

Fvirtman
Fvirtman
Niveau 10
04 décembre 2007 à 11:59:23

Ces manques que j´ai viennent du fait qu´on m´a enseigné le C89, et que donc je me suis toujours appuyé dessus...
Mais il faut savoir évoluer :-)

Fvirtman
Fvirtman
Niveau 10
04 décembre 2007 à 12:17:14

Bon, le DUMP m´a bien montré que les données en plus suivaient directement les données de la structure. (au moins sur mon compilo).
Apres, comme je disais plus haut : pour un tableau de structures a taille variable, ça doit etre complexe gérer pour le compilo !

Je me suis donc dit : je vais faire un tel tableau, pour tenter un DUMP, et la, le compilo me rassure : c´est pas complexe a gérer pour la simple raison que... ça ne se gere pas !!

struct Foo foo0[] = {
{ 5,{6,7,8,9,10} },
{ 5,{6,7} },
{ 5,{6} },
{ 5,{6} },
{ 5,{6,7,8,9,10,11,12,13,14,15} },
{ 5,{6,7,8,9,10,11} }
};

error C2233: ´foo0´ : arrays of objects containing zero-size arrays are illegal

Bon, j´ai mieux compris le concept !
merci bien en tout cas !

kufa
kufa
Niveau 9
04 décembre 2007 à 15:55:08

erf desole lag taf
oui effectivement, tu peux pas avoir des structs de structs avec des flexible arrays. Normal, a cause de la taille inconnue :)
Si tu veux la taille exacte, a toi de la stocker qqpart.

Sous forums
  • Aide à l'achat Mac
  • Macintosh
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Internet
  • Steam Deck
  • Hardware
La vidéo du moment