[c++] struct 2 bytes groter dan members opgeteld..

Pagina: 1
Acties:
  • 120 views sinds 30-01-2008
  • Reageer

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Ik zit hier met structs te klooien in C++.

En het valt me op dat wanneer ik sizeof los laat op de struct, dat deze dan altijd 2 bytes groter is dan de sizeof van de individuele members bij elkaar opgeteld.

Is hier een reden voor? En wat is de betekenis van deze twee bytes? Ik gebruik hier VC++ 6.0 als compiler.


Ik dacht altijd dat een struct eenvoudig was dat de members sequentieel in het geheugen staan.

Deze:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    /*
     * Info nodig per Activiteit (1070 bytes):
     * - ObjectType Activiteit  (enum (4 byte))
     * - naam Activiteit        (string (30 bytes))
     * - status Activiteit      (enum (4 bytes))
     * - deadline Activiteit    (time_t (4 bytes))
     * - notition Activiteit    (string (1024 bytes))
     * - aantal Registraties    (UINT (4 bytes))
     */
struct ActivityStruct {
    ObjectType objectType;
    char name[30];
    Status status;
    time_t deadline;
    char notition[1024];
    UINT numberOfRegistrations;
};

, wordt met sizeof een 1072 bytes...

Terwijl deze:
code:
1
2
3
4
5
6
7
8
9
10
11
    /*
     * Info nodig per Registratie (12 bytes)
     * - ObjectType Registratie (enum (4 byte))
     * - start Activiteit       (time_t (4 bytes))
     * - einde Activiteit       (time_t (4 bytes))
     */
struct RegistrationStruct {
    ObjectType objectType;
    time_t start;
    time_t end;
};

, wel 12 bytes wordt met sizeof, 't wordt vager en vager.

  • JayTaph
  • Registratie: Oktober 1999
  • Laatst online: 28-11-2025

JayTaph

Portability is for canoes.

Structs worden per definitie aligned opgeslagen.
code:
1
2
3
4
typedef struct {
  char  c;
  int i;
} Tblaat;

geeft waarschijnlijk een sizeof van 8 ipv de verwachte 5.


edit:

Shit, me theorie klopt :+.. Je 30 bytes lange string wordt intern omgezet naar 32 bytes, vandaar de 2 bytes extra, de rest is namelijk een veelvoud van 4.

Als je dit expliciet niet wil (ROM-structures zoals VESAinfo etcetera vinden deze optimalisatie NIET fijn :)), kan je de pragma __packed__ gebruiken..

Yo dawg, I heard you like posts so I posted below your post so you can post again.


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Op zaterdag 15 december 2001 00:27 schreef JayTaph het volgende:
Structs worden per definitie aligned opgeslagen.
code:
1
2
3
4
typedef struct {
  char  c;
  int i;
} Tblaat;

geeft waarschijnlijk een sizeof van 8 ipv de verwachte 5.
Maar als ik de bytes van de struct letterlijk weg schrijf naar file, de volledige 1072 en ik lees die 1072 weer in de struct, dan gaat het goed dus.

  • JayTaph
  • Registratie: Oktober 1999
  • Laatst online: 28-11-2025

JayTaph

Portability is for canoes.

Maar als ik de bytes van de struct letterlijk weg schrijf naar file, de volledige 1072 en ik lees die 1072 weer in de struct, dan gaat het goed dus.
Je moet altijd de sizeof(struct) gebruiken ipv een hardcoded getal. Maar ik denk dat je gewoon 2 bytes voor de laatste variabele niet wegschrijft en inleest als je 1072 gaat gebruiken ipv sizeof(struct)

sorry.. 1072 zal dus wel goed gaan, (maar nog steeds niet aan te raden)

Yo dawg, I heard you like posts so I posted below your post so you can post again.


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Uiteraard gebruik ik sizeof... :)

Ik lees gewoon sizeof(deBetreffendeStruct) bytes in beginnend op het geheugenadres in een pointer naar een instantie van deBetreffendeStruct.

  • JayTaph
  • Registratie: Oktober 1999
  • Laatst online: 28-11-2025

JayTaph

Portability is for canoes.

Da moet gewoon goed gaan lijkt me..
code:
1
2
3
4
5
6
7
8
9
typedef struct {
  char c;
  int i;
} TBLAAT;

TBLAAT blaat, blaat2;

fwrite (&blaat, 1, sizeof(TBLAAT), f);
fread (&blaat2, 1, sizeof(TBLAAT), f);

dan zou blaat2 idd hetzelfde moeten bevatten als blaat..

Yo dawg, I heard you like posts so I posted below your post so you can post again.


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Is het ook goed als ik WriteFile en ReadFile gebruik ;)
Bedankt voor de hulp, weer wat geleerd.

Thread closed.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:17

.oisyn

Moderator Devschuur®

Demotivational Speaker

je hebt het alleen niet goed geleerd (no offense, JayTaph) :)

om bij hetzelfde voorbeeld te blijven:
code:
1
2
3
4
5
struct blaat
{
    char c;
    int i;
};

sizeof (blaat) is hier idd 8, omdat die int wordt gealigned op 4 bytes (zoals JayTaph ook aangeeft)

maar bij de volgende struct:
code:
1
2
3
4
5
struct blaat
{
    char c;
    short s;
};

is sizeof (blaat) echter maar 4

Je kunt bij de meeste compilers een struct/class member alignment instellen (bij MSVC++ is dit default 8). Alle members die kleiner zijn dan de alignment worden aligned op hun eigen grootte, alle members die groter zijn dan de alignment worden aligned op de opgegeven alignment.

Oftewel, bij een alignment van 4 worden char, short en int aligned op respectivelijk 1, 2 en 4, en alles groter dan 4(double bijvoorbeeld) wordt aligned op 4

als je bij de struct die je gaf na die chararray een short had staan, dan krijg je dus geen extra bytes ertussen, aangezien de short dan perfect op 2 aligned was (30 is tenslotte een veelvoud van 2)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:17

.oisyn

Moderator Devschuur®

Demotivational Speaker

en die __packed__ attribute is trouwens iets van gcc

vc++ gebruikt hiervoor #pragma pack([push|pop,] <alignment>)

dat pushen en poppen is echt handig om het terug te zetten naar de vorige waarde

als je bijvoorbeeld effe 1 struct moet packen met 1, dan doe je dus
code:
1
2
3
4
5
6
#pragma pack (push, 1)
struct blaat
{
    ...
};
#pragma pack (pop)

The - DDD: trouwens, waarom heb ik jou nog niet gezien op het gameskool forum? :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • JayTaph
  • Registratie: Oktober 1999
  • Laatst online: 28-11-2025

JayTaph

Portability is for canoes.

Ik heb ook nooit gezegd dat het *altijd* een veelvoud van 4 moet zijn :+, ik ging eventjes uit van een alignment van 4. (Ik gebruik nooit vc, maar goed, 4 verklaarde mooi de 2 bytes tussenruimte iig).

Alignments zijn en blijven altijd tricky dingen omdat het echt iets is waar elke compiler een andere interpretatie (per default) aan wil geven. Ik heb ook geen flauw idee wat gcc standaard met die struct gaat doen, of de cc van tru64 (maandag ff uitproberen). Gewoon *geen* assumpties maken dus qua grootte (maar dat mag je eigenlijk zowiezo niet doen), of anders __packed__ gaan gebruiken als je heel eigenwijs wilt zijn (ik gebruik het vaak, staat iemand daarvan raar te kijken :+)

Maar goed, tenzij iemand de moeite wil nemen om een heel verhaal op te schrijven waarom alignment zo belangrijk is voor een cpu en de memory-bussen denk ik dat osyn het netjes heeft afgerond :)

Yo dawg, I heard you like posts so I posted below your post so you can post again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 23:11
Op zaterdag 15 december 2001 01:29 schreef OiSyN het volgende:
je hebt het alleen niet goed geleerd (no offense, JayTaph) :)

[..]

Je kunt bij de meeste compilers een struct/class member alignment instellen (bij MSVC++ is dit default 8). Alle members die kleiner zijn dan de alignment worden aligned op hun eigen grootte, alle members die groter zijn dan de alignment worden aligned op de opgegeven alignment.

Oftewel, bij een alignment van 4 worden char, short en int aligned op respectivelijk 1, 2 en 4, en alles groter dan 4(double bijvoorbeeld) wordt aligned op 4
Sorry, OySiN, maar dat heb JIJ dus niet goed.
Alinignment is een reden voor een compiler om dingen niet volledig packed neer te zetten, maar op een (vaste) afstand afhankelijk van de betrokken types. Dat is het enige wat je kunt zeggen zonder specifiek op een architectuur/compiler in te gaan.
Overigens is het niet ongebruikelijk dat sizeof(double)==8, maar dat ze aligned zijn op 4 bytes.
als je bij de struct die je gaf na die chararray een short had staan, dan krijg je dus geen extra bytes ertussen, aangezien de short dan perfect op 2 aligned was (30 is tenslotte een veelvoud van 2)
Dat is 1 mogelijkheid. Een andere is dat de compiler sowieso alle structs op 4 bytes aligned.

C++ specifiek: Een compiler mag members reshuffelen, als er een access specifier(public|protected}private) in een class/struct staat. Daar moet je ook rekening mee houden, alleen hier niet.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Op zaterdag 15 december 2001 01:40 schreef OiSyN het volgende:
The - DDD: trouwens, waarom heb ik jou nog niet gezien op het gameskool forum? :)
Is dat al online dan... :P

Ik zal is even kijken.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:17

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op zaterdag 15 december 2001 11:05 schreef MSalters het volgende:

[..]

Sorry, OySiN, maar dat heb JIJ dus niet goed.
Alinignment is een reden voor een compiler om dingen niet volledig packed neer te zetten, maar op een (vaste) afstand afhankelijk van de betrokken types. Dat is het enige wat je kunt zeggen zonder specifiek op een architectuur/compiler in te gaan.
uhm ik ging dus specifiek op de msvc++ compiler in, want daar ging het hier over :z

(en mijn naam is OiSyN ;))

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1