[c] Structures als functie argument

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

  • J.Hollemans
  • Registratie: September 2001
  • Laatst online: 03-10-2025
Ik heb de volgende c code (geen c++):
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>

struct point
{
  int x;
  int y;
};

struct rechthoek
{
  struct point punt1;
  struct point punt2;
};

double omtr (struct rechthoek rh)
{
  return (2 * (rh.punt2.y - rh.punt1.y) + 2 * (rh.punt2.x - rh.punt1.x));
}

int main()
{
  struct rechthoek testRechthoek;
  double omtrek;

  testRechthoek.punt1.x = 12;
  testRechthoek.punt1.y = 15;
  testRechthoek.punt2.x = 22;
  testRechthoek.punt2.y = 35;

  omtrek = omtr(testRechthoek);

  printf("punt1.x:\t%d\n", testRechthoek.punt1.x);
  printf("punt1.y:\t%d\n", testRechthoek.punt1.y);
  printf("punt2.x:\t%d\n", testRechthoek.punt2.x);
  printf("punt2.y:\t%d\n", testRechthoek.punt2.y);

  printf("De omtrek is:\t%d", omtrek);

  return 0;
}

Tijdens het compilen krijg ik geen foutmelding. Wanneer
ik dit proggie run krijg ik uit de omtrek de waarde 0.

Het lijkt er op, dat ik geen structure als functieargument
kan gebruiken. Is dat ook zo of doe ik iets fout :?

Far from being some stuffy science, writing regular expressions is closer to an art.


  • stylee
  • Registratie: December 2000
  • Laatst online: 04-09-2021

stylee

blah zeg ik je

code:
1
printf("De omtrek is:\t%E", omtrek);

Je printf dingetje klopte niet :) Je moet wel ff afronden op 2 cijfers achter de komma oid, zie printf help...

en owja, je kan structures gewoon doorgeven aan functies, maar onthoud wel dat je niet de waardes in de structure zelf doorgeeft maar een pointer (netals arrays), maar dat wist je waarschijnlijk al :)

  • J.Hollemans
  • Registratie: September 2001
  • Laatst online: 03-10-2025
|:( stom van dat %E, logisch...
zie printf help...
je bedoelt zeker de printf manpages ;)

en dat van die pointer was idd bekend. thnx !

Far from being some stuffy science, writing regular expressions is closer to an art.


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op zaterdag 06 oktober 2001 10:41 schreef stylee het volgende:
en owja, je kan structures gewoon doorgeven aan functies, maar onthoud wel dat je niet de waardes in de structure zelf doorgeeft maar een pointer (netals arrays), maar dat wist je waarschijnlijk al :)
ERRR wrong. Hij geeft hier de struct by-value door oftewel de functie krijgt een unieke kopie van de struct. Om overhead te voorkomen dien je by-reference of by-value door te geven, zonodig met const, bijv.:
code:
1
2
3
4
double omtr (const struct rechthoek &rh)
{
  return (2 * (rh.punt2.y - rh.punt1.y) + 2 * (rh.punt2.x - rh.punt1.x));
}

Professionele website nodig?


Verwijderd

(En nee, references bestaan niet in C; als je niet dat hele struct-ding by value door wil geven moet het ff met een pointertje.)

  • stylee
  • Registratie: December 2000
  • Laatst online: 04-09-2021

stylee

blah zeg ik je

curry684: ERRR wrong. Hij geeft hier de struct by-value door oftewel de functie krijgt een unieke kopie van de struct...

Hmmm... dat heb ik toch echt op school geleerd he :? ff K&R erop naslaan... shit uitgeleend :'( Dan maar ff snel testen..
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>

typedef struct {
    int i;
} b_t;

void foo();

int main (int argc, char* argv[]) {
    b_t bar;    

    bar.i = 10;
    printf ("Voor functie-aanroep: %d\n", bar.i);

    foo (bar);
    printf ("Na functie-aanroep: %d\n", bar.i);

}

void foo (b_t b) {
    b.i = 100;
}


code:
1
2
Voor functie-aanroep: 10
Na functie-aanroep: 10

Hmm idd je hebt gelijk, maandag toch ff mijn C leraar aanspreken :(

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 16:35
in c geeft je een struct door dmv een pointer

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Verwijderd

Volgens mij zijn jullie in de war met arrays. Structs worden by-value doorgegeven, arrays by-reference. (Een array is niet veel meer dan een pointer in c.)

  • J.Hollemans
  • Registratie: September 2001
  • Laatst online: 03-10-2025
farlane wrote:
in c geeft je een struct door dmv een pointer
dat moet toch alleen als je de waarde van je struct wilt
wijzigen ?

toch niet als je de waarden van je struct wilt gebruiken
om iets te berekenen...

Far from being some stuffy science, writing regular expressions is closer to an art.


Verwijderd

Op zaterdag 06 oktober 2001 15:06 schreef JeroenHollemans het volgende:
toch niet als je de waarden van je struct wilt gebruiken
om iets te berekenen...
Tuurlijk, als je een kleine struct gebruikt kun je best pass-by-value gebruiken, maar als de struct groot wordt is het efficienter een pointer naar die struct te passen. Als je zeker wilt zijn dat je functie de struct niet kan wijzigen, pass je een const pointer.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op zaterdag 06 oktober 2001 14:44 schreef Sneech het volgende:
(En nee, references bestaan niet in C; als je niet dat hele struct-ding by value door wil geven moet het ff met een pointertje.)
Excusez-moi, iets teveel C++ :) Essentie blijft hetzelfde.

Professionele website nodig?


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18-09 18:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

ik vraag me trouwens af waarom je een double gebruikt, aangezien de omtrek altijd een geheel getal zal zijn :)

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.


Verwijderd

Waarom gebruik je eigenlijk een double om de omtrek in op te slaan, als je ints gebruikt voor de width & height? Je kan voor het resultaat dan beter longs nemen.

Met die long kan je dan ook nog iets bijzonders doen: een geheel getal vermenigvuldigen met twee is hetzelfde als de bits een stapje opschuiven (x * 2 == x << 1). Maar dit laatste zal waarschijnlijk al door je compiler gedaan worden (dit laatste werkt niet op de juiste manier als je een double gebruikt).

Kunnen de punt.x, punt.y ook negatief zijn? Als dat niet het geval is zou je een unsigned int kunnen gebruiken, dan kan je grotere positieve getallen opslaan in de variable. Bovendien is int platvorm afhankelijk, gangbaar is dat een int 4 bytes is (gelijk aan een long), maar het zou ook twee bytes kunnen zijn (een short). Dus i.p.v. van een int, gebruik een short int of een long int. Nu moet je er ook niet altijd vanuit gaan dat een short int 2 bytes zijn en een long int 4 bytes... deze zijn natuurlijk ook systeem afhankelijk, maar ze geven al iets meer aan in welke grootte-klasse je die variable moet indelen.

bovendien kan je omtrek niet negatief zijn, dus bij het berekenen moet je absoluut-waarden over de - gebruiken. In dat geval kan je beter een unsigned type variable gebruiken. D.m.v. twee ifjes bepaal je dan of je x1-x2 doet of x2-x1 (idem voor y).

En dan nog even een benchmark: de pass-by-value versie is iets langzamer dan de pass-by-refererce (d.m.v. een pointer). Echter, omdat het hier om een kleine struct gaat en je bovendien alle waarden van de struct gebruikt, scheelt het niet zoveel.

Na ja, zoek maar uit wat je doet, dit even om te illustreren hoeveel mogelijkheden je wel niet hebt :)

edit: ik zie nu dat OiSyN dat ook al afvroeg :)

Verwijderd

mmm...
x * 2 == x << 2
moet dat niet x * 2 == x << 1 als in 2^1 zijn?

Dus een shift van 1 bit?

Verwijderd

mmm...

moet dat niet x * 2 == x << 1 als in 2^1 zijn?

Dus een shift van 1 bit?
Oeps, zat te veel naar de twee te kijken. Als je in de tekst schrijft dat je alle bits 1 positie gaat opschuiven, dan moet je natuurlijk niet in de code dat met twee posities doen |:(
dus: 2*x == x<<1;

  • J.Hollemans
  • Registratie: September 2001
  • Laatst online: 03-10-2025
waarom gebruik je een double
Ik heb daar niet echt over nagedacht....
maar wie kan er een overzichtje geven van de (std) datatypes,
geheugenlengte in bytes (uitgaande van een 32-bits os.)
en indeling van het geheugen (bijv. welk bit geeft aan,
dat een getal positief/negatief is)

Far from being some stuffy science, writing regular expressions is closer to an art.


Verwijderd

tip: koop een boek over (c en/of c++), daar staat dit soort dingen in. Ook hoe je aan de hand van de bitrij tot de waarde van een (un)signed aantal bytes komt.

  • J.Hollemans
  • Registratie: September 2001
  • Laatst online: 03-10-2025
tip: koop een boek over (c en/of c++), daar staat dit soort dingen in. Ook hoe je aan de hand van de bitrij tot de waarde van een (un)signed aantal bytes komt.
Ik bedoel:
stel ik heb een int. deze gebruikt in een 32-bits os
4 bytes aan geheugen. Als ik er 1 bitje af haal (voor
positieve/negatieve notatie) blijven er 31 over.

2^31 = 2147483648 mogelijkheden. Wanneer ik dit aan een
integer toeken (en daarna compileer) krijg ik de waarschuwing:
decimal constant is so large that it is unsigned
als ik er 2147483647 van maak doet 'ie het wel.

hoe is dit dan mogelijk ?

Far from being some stuffy science, writing regular expressions is closer to an art.


Verwijderd

Je vergeet de 0 mee te tellen dummy..

Verwijderd

die 0 telt ook mee als combinatie! Bij n bits is de maximum waarde:
2**n-1 (even uitgaande dat het over een unsigned waarde gaat)

ofwel een set: (0, 1, 2, ..., 2**n-1)
aantal combinaties: #(0, 1, 2, ..., 2**n-1) = 2**n

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18-09 18:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

offtopic:
jippieieieieie 1000e post!!! :)


bij negatieve getallen kun je wel tot -2147483648. Nu hoeft de 0 namelijk niet meegeteld te worden want dat heb je al gedaan bij positieve getallen

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.


Verwijderd

Op zaterdag 06 oktober 2001 16:45 schreef OiSyN het volgende:
offtopic:
jippieieieieie 1000e post!!! :)
Als je nu niet meer post blijft ie er mooi op staan ook :Y)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18-09 18:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op zaterdag 06 oktober 2001 16:47 schreef Yarvieh het volgende:

[..]

Als je nu niet meer post blijft ie er mooi op staan ook :Y)
ja precies, effe snel een andere account aanmaken....

ooooh shit te laat, 1001 :)

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.


  • J.Hollemans
  • Registratie: September 2001
  • Laatst online: 03-10-2025
Op zaterdag 06 oktober 2001 16:40 schreef Yarvieh het volgende:
Je vergeet de 0 mee te tellen dummy..
:X

Far from being some stuffy science, writing regular expressions is closer to an art.


Verwijderd

offtopic:
jippieieieieie 1000e post!!! :)
Tss. Een echte tweaker gaat pas juichen bij de 1024 ste post >:)
bij negatieve getallen kun je wel tot -2147483648. Nu hoeft de 0 namelijk niet meegeteld te worden want dat heb je al gedaan bij positieve getallen
bij een signed bitrij:

Een n bitsrij heeft dan een bereik van:

-(2**n) tot/met 2**n-1

waarbij over het de bit van de hoogste orde bepaalt of de bits eronder een positief of negatief getal voorstellen (iets wat ooit afgesproken is). Een signed positief getal < 2**(n-1) heeft dezelfde bitrij als een unsigned positief getal < 2**(n-1). Voor negatieve getallen moet je de bits tot n anders interpreteren, maar hoe dat gaat kan je vast wel ergens op internet vinden (ik heb dat nog wel ergens in een boek staan... onder het kopje complement nogwat ofzo).

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18-09 18:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op zaterdag 06 oktober 2001 16:54 schreef lnfinitive het volgende:

[..]

Tss. Een echte tweaker gaat pas juichen bij de 1024 ste post >:)
eigenlijk wilde ik pas gaan juigen bij de 4294967296, maar ik denk niet dat ik dat haal... (en de database ook niet :))
bij een signed bitrij:

Een n bitsrij heeft dan een bereik van:

-(2**n) tot/met 2**n-1

waarbij over het de bit van de hoogste orde bepaalt of de bits eronder een positief of negatief getal voorstellen (iets wat ooit afgesproken is). Een signed positief getal < 2**(n-1) heeft dezelfde bitrij als een unsigned positief getal < 2**(n-1). Voor negatieve getallen moet je de bits tot n anders interpreteren, maar hoe dat gaat kan je vast wel ergens op internet vinden (ik heb dat nog wel ergens in een boek staan... onder het kopje complement nogwat ofzo).
lever je ook nog een toegevoegde waarde of herhaal je altijd alles wat iedereen zegt, maar dan met meer woorden ;)

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.


Verwijderd

Op zaterdag 06 oktober 2001 16:54 schreef lnfinitive het volgende:
Voor negatieve getallen moet je de bits tot n anders interpreteren, maar hoe dat gaat kan je vast wel ergens op internet vinden (ik heb dat nog wel ergens in een boek staan... onder het kopje complement nogwat ofzo).
Heel simpel: "flip the bits, plus one". Voorbeeld:
code:
1
2
3
4
5
6
negatieve bitreeks: 11110100

flip the bits:  00001011
plus 1:      00000001 =
              --------
              00001100

1110100 is dus -12. Omrekenen naar negatief gaat exact het zelfde:
code:
1
2
3
4
5
6
bitreeks:        00000001

flip the bits:  11111110
plus 1:      00000001
              --------
              11111111

-1 is dus 11111111.

Dit gegoochel met bits heeft als voordeel dat er maar één representatie voor nul is:
code:
1
2
3
4
5
6
bitreeks:        00000000

flip the bits:  11111111
plus 1:      00000001
              --------
             [1]00000000

Dat negende 1 bit tussen haken valt weg in een achtbits representatie, zodat -0 == 0.

  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 19-09 17:21
lever je ook nog een toegevoegde waarde of herhaal je altijd alles wat iedereen zegt, maar dan met meer woorden ;)
:s Grr. iedereen is me altijd net even voor... enne, om dus even precies op te schrijven wat jij bedoelde met "bij negatieve getallen kun je wel tot -2147483648".

Bovendien vroeg de topicstarter om aan tegeven welke bit dat aangeeft. Dat had jij er niet bij staan.

Vandaar, ook nog bedankt met je post, hermetische geopend mietje, weet ik het ook weer hoe het zat met negatieve getallen.

BTW counter-attack: lever je ook nog eens toegevoegde waarde zonder er nog een aantal topics bij te zetten met onzin er in, zoals het aantal posts dat je al wel niet gehaald hebt ;)

Dan komt hier nog even mijn bijdrage:
maar wie kan er een overzichtje geven van de (std) datatypes,
geheugenlengte in bytes (uitgaande van een 32-bits os.)
Een greep uit typen: short (int), int, long (int), enum, struct, double, float.

Met de sizeof(<type>), bijv: sizeof(int), kan je opvragen hoeveel bytes dat type in beslag neemt. In je code is dit een normaal getal en wordt op compile-time berekend (voor zover mij bekend). Sommige typen (enum en struct) veranderen zijn uit zichzelf niet van een bepaalde grootte, vandaar dat je altijd moet zeggen waar die enum of struct uit bestaat.

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


Verwijderd

Op zaterdag 06 oktober 2001 19:16 schreef Infinitive het volgende:
BTW counter-attack: lever je ook nog eens toegevoegde waarde ....blablabla
Euhh is het nodig toegevoegde waarde te hebben dan tegenwordig? Ik bral meestal maar wat eigenlijk.. (8>

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18-09 18:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op zaterdag 06 oktober 2001 19:24 schreef Yarvieh het volgende:

[..]

Euhh is het nodig toegevoegde waarde te hebben dan tegenwordig? Ik bral meestal maar wat eigenlijk.. (8>
ja maar van jou zijn we dat gewend ;)

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: 18-09 18:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op zaterdag 06 oktober 2001 19:16 schreef Infinitive het volgende:

Een greep uit typen: short (int), int, long (int), enum, struct, double, float.
enum en struct zijn natuurlijk geen typen, maar worden gebruikt om typen mee te declareren
je bent overigens de char vergeten, en de union als broertje van de struct :)

over het algemeen is het:

char: 8 bits
short: 16 bits
long: 32 bits
float: 32 bits (1 bit voor het teken, 8 bits exponent en 24 bits mantissa)
double: 64 bits (1 bit voor het teken, 11 bits exponent en 52 bits mantissa)

de int is meestal gelijk aan de short op 16-bits platformen en gelijk aan de long op 32-bits platformen

hier een goed documentje over de IEEE floating point standaard :)

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.


  • stylee
  • Registratie: December 2000
  • Laatst online: 04-09-2021

stylee

blah zeg ik je

offtopic:
Dat bit shiften, heeft iemand daar ergens een goede uitleg voor staan? Ziet er nl. waanzinnig cool uit * stylee wil het ook kennen B-)

K&R gaat er niet zo diep in, andere boeken/sites oid?

thx

  • J.Hollemans
  • Registratie: September 2001
  • Laatst online: 03-10-2025
Infinitive schreef:
Met de sizeof(<type>), bijv: sizeof(int), kan je opvragen hoeveel bytes dat type in beslag neemt. In je code is dit een normaal getal en wordt op compile-time berekend (voor zover mij bekend). Sommige typen (enum en struct) veranderen zijn uit zichzelf niet van een bepaalde grootte, vandaar dat je altijd moet zeggen waar die enum of struct uit bestaat.
hoe komt het dan, dat:
code:
1
2
3
4
5
6
7
8
9
struct test
{
  int a, b;
  char *str, ch;
  int *arr;
};

struct test t1;
printf("%d\n", sizeof(t1));

met de waarde 20 komt, terwijl:
code:
1
2
3
4
5
2 * int (a en b)     = 2 * 4 = 8
2 * ptr (*str en *arr) = 2 * 4 = 8
char ch             = 1 +
                      ---
                      17

hieruit 17 komt :?

Far from being some stuffy science, writing regular expressions is closer to an art.


  • J.Hollemans
  • Registratie: September 2001
  • Laatst online: 03-10-2025
mietje schreef:
code:
1
2
3
4
5
6
bitreeks:    00000000

flip the bits:  11111111
plus 1:    00000001
            --------
         [1]00000000

Dat negende 1 bit tussen haken valt weg in een achtbits representatie, zodat -0 == 0.
en de bitreeks 10000000 dan ?
code:
1
2
3
4
5
6
bitreeks:    10000000

flip the bits:  01111111
plus 1:    00000001
            --------
            10000000

daar komt toch -0 uit ?

Far from being some stuffy science, writing regular expressions is closer to an art.


Verwijderd

JeroenHollemans>> dat fenomeen heet padding (opvulling) heeft te maken met alignment (uitlijning). Een 32bits cpu leest het liefst 4 bytes in een keer, en de meeste cpu's kunnen dat alleen als een geheugenadres deelbaar is door 4; anders moet er 2x gelezen worden. Om dit dubbel inlezen te voorkomen worden datastructuren gepad zodat hun size een veelvoud van 4 is, zodat een array van die datastructuren automatisch gealigned is. Zo win je dus snelheid ten koste van geheugenruimte.

Verwijderd

Op zaterdag 06 oktober 2001 22:55 schreef JeroenHollemans het volgende:
en de bitreeks 10000000 dan ?
...
daar komt toch -0 uit ?
Nee :) Het 8-bit is 1 dus het moet per definitie een negatief getal zijn. Als we de waarde in meer bits berekenen blijkt deze -128 te zijn. Het kleinste getal dat je met een 8bit integer kunt weergeven is dus -128 (-27), en het grootste 127 (27-1) zoals eerder (bijna correct) vermeld. Dat dit niet symmetrisch is, komt omdat er maar éen waarde voor nul is. De voordelen van een nulwaarde wegen veruit op tegen dit symmetrie-probleem.

<edit>
Bijna correct, wat het bereik van een n-bit integer is dus [-1 * 2(n-1) , 2(n-1)-1].
</edit>

  • J.Hollemans
  • Registratie: September 2001
  • Laatst online: 03-10-2025
Op zaterdag 06 oktober 2001 23:00 schreef mietje het volgende:
JeroenHollemans>> dat fenomeen heet padding (opvulling) heeft te maken met alignment (uitlijning). Een 32bits cpu leest het liefst 4 bytes in een keer, en de meeste cpu's kunnen dat alleen als een geheugenadres deelbaar is door 4; anders moet er 2x gelezen worden. Om dit dubbel inlezen te voorkomen worden datastructuren gepad zodat hun size een veelvoud van 4 is, zodat een array van die datastructuren automatisch gealigned is. Zo win je dus snelheid ten koste van geheugenruimte.
thnx, dat moet je ook maar net ff weten zeg...

Far from being some stuffy science, writing regular expressions is closer to an art.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18-09 18:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op zaterdag 06 oktober 2001 22:55 schreef JeroenHollemans het volgende:

[..]

en de bitreeks 10000000 dan ?
code:
1
2
3
4
5
6
bitreeks:    10000000

flip the bits:  01111111
plus 1:    00000001
            --------
            10000000

daar komt toch -0 uit ?
nee, zoals mietje al heeft uitgelegd. Je kunt het echter ook anders zien.

bitreeks 11111111 stelt het getal -1 voor, niet -127. Dat is ook logisch, omdat dat makkelijker werkt met berekeningen; je hoeft nergens rekening mee te houden. Als je bijvoorbeeld het getal 0 hebt, en je trekt daar 1 vanaf, dan krijg je dus als uitkomst

00000000 - 00000001 = 11111111

en -2 heeft dan als bitreeks 11111110. Als je nou door gaat rekenen, dan kom je op 10000000 = -128

Als je nou het teken gaat veranderen op de manier van mietje, dus alle bits omzetten, en er 1 bij op tellen dan kom je weer op 10000000 uit. Ook dat is logisch, want denk eens na:
-(-128) = 128
128 past niet in een signed 8-bits getal, die gaat immers maar tot 127. 127 heeft als bitreeks 01111111. Als je daar 1 bij optelt (om er 128 van te maken), dan krijg je weer -128 :)

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: 18-09 18:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op zaterdag 06 oktober 2001 23:00 schreef mietje het volgende:
JeroenHollemans>> dat fenomeen heet padding (opvulling) heeft te maken met alignment (uitlijning). Een 32bits cpu leest het liefst 4 bytes in een keer, en de meeste cpu's kunnen dat alleen als een geheugenadres deelbaar is door 4; anders moet er 2x gelezen worden. Om dit dubbel inlezen te voorkomen worden datastructuren gepad zodat hun size een veelvoud van 4 is, zodat een array van die datastructuren automatisch gealigned is. Zo win je dus snelheid ten koste van geheugenruimte.
deze uitleg klopt niet helemaal. Het wordt namelijk niet gepad om de grootte van de struct een veelvoud van 4 te laten zijn, maar de laatste int *arr uit de struct wordt aligned op een veelvoud van 4. Elke variabele wordt namelijk aligned op z'n grootte, dus een short op 2 bytes, een int (in geval van 32 bits), long, float en pointers op 4 bytes, en doubles op 8 bytes.

de layout van de struct ziet er dan als volgt uit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
struct test
{
  int a, b;
  char *str, ch;
  int *arr;
};

offset  size  var
 0  4     int a
 4  4     int b
 8  4     char * str
12  1     char ch
16  4     int * arr  <-- deze wordt aligned

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.


Verwijderd

Op zondag 07 oktober 2001 00:21 schreef OiSyN het volgende:
deze uitleg klopt niet helemaal.
Ik zeg toch niet waar er gepad wordt ;) Ik weet dat m'n uitleg niet compleet was en niet helemaal goed is, maar dat is de jouwe ook niet :) Ik wilde het niet al te complex maken. Voorbeeldje:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdlib.h>
#include <stdio.h>

struct s {
  short s1;
  char  b1;
};

struct b {
  char b1, b2, b3;
};

int main(void) {
  printf("Structsize s: %i b: %i\n", sizeof(struct s), sizeof(struct b));
  return EXIT_SUCCESS;
}

Output (met gcc):
code:
1
Structsize s: 4 b: 3

Nu jij weer :) Struct padding is bijzonder lastig correct te omschrijven.

<edit>Oeps, verkeerde code gepost.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18-09 18:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

jij hebt mijn uitleg niet goed gelezen :)

er wordt niet gepad om de size van de struct op zoveel bytes te alignen (wat jij dus zegt), maar er wordt gepad om elementen in de struct op zoveel bytes te alignen

sizeof (short) = 2, dus shorts worden op 2 bytes aligned. De 1e struct is dus 4, omdat de short van het 2e element in een mogelijke struct-array weer op 2 bytes aligned moet worden

sizeof (char) = 1, dus chars worden op 1 byte gealigned, dus de size van die 2e struct is 3, klaar :)

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.


Verwijderd

Op zondag 07 oktober 2001 16:58 schreef OiSyN het volgende:
er wordt niet gepad om de size van de struct op zoveel bytes te alignen (wat jij dus zegt), maar er wordt gepad om elementen in de struct op zoveel bytes te alignen
Ok, maar hoe zit het dan met:
sizeof (short) = 2, dus shorts worden op 2 bytes aligned. De 1e struct is dus 4, omdat de short van het 2e element in een mogelijke struct-array weer op 2 bytes aligned moet worden
Hier pad je dus wel degelijk om de size van de struct te alignen, er is voor de rest geen enkele noodzaak om er een loos byte achter te plakken.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op zaterdag 06 oktober 2001 23:48 schreef JeroenHollemans het volgende:
thnx, dat moet je ook maar net ff weten zeg...
Daarom is enige assembler-ervaring zo verschrikkelijk nuttig bij het schrijven van goede C/C++, omdat je dan optimalisaties waarvan je weet dat de CPU er het snelste mee wordt alvast met de hand kan uitvoeren zodat a) het zelfs in debugmode snel is en b) je dan zeker weet dat een bepaalde optimalisatie wordt uitgevoerd.

En die limits van integrale typen vind je in limits.h, oftewel:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#define CHAR_BIT    8      /* number of bits in a char */
#define SCHAR_MIN   (-128)  /* minimum signed char value */
#define SCHAR_MAX     127    /* maximum signed char value */
#define UCHAR_MAX     0xff  /* maximum unsigned char value */

#ifndef _CHAR_UNSIGNED
#define CHAR_MIN    SCHAR_MIN   /* mimimum char value */
#define CHAR_MAX    SCHAR_MAX   /* maximum char value */
#else
#define CHAR_MIN    0
#define CHAR_MAX    UCHAR_MAX
#endif  /* _CHAR_UNSIGNED */

#define MB_LEN_MAX    5      /* max. # bytes in multibyte char */
#define SHRT_MIN    (-32768)      /* minimum (signed) short value */
#define SHRT_MAX    32767      /* maximum (signed) short value */
#define USHRT_MAX     0xffff      /* maximum unsigned short value */
#define INT_MIN     (-2147483647 - 1) /* minimum (signed) int value */
#define INT_MAX  2147483647    /* maximum (signed) int value */
#define UINT_MAX    0xffffffff    /* maximum unsigned int value */
#define LONG_MIN    (-2147483647L - 1) /* minimum (signed) long value */
#define LONG_MAX    2147483647L   /* maximum (signed) long value */
#define ULONG_MAX     0xffffffffUL  /* maximum unsigned long value */

#if     _INTEGRAL_MAX_BITS >= 8
#define _I8_MIN     (-127i8 - 1)    /* minimum signed 8 bit value */
#define _I8_MAX  127i8     /* maximum signed 8 bit value */
#define _UI8_MAX    0xffui8  /* maximum unsigned 8 bit value */
#endif

#if     _INTEGRAL_MAX_BITS >= 16
#define _I16_MIN    (-32767i16 - 1) /* minimum signed 16 bit value */
#define _I16_MAX    32767i16    /* maximum signed 16 bit value */
#define _UI16_MAX     0xffffui16    /* maximum unsigned 16 bit value */
#endif

#if     _INTEGRAL_MAX_BITS >= 32
#define _I32_MIN    (-2147483647i32 - 1) /* minimum signed 32 bit value */
#define _I32_MAX    2147483647i32 /* maximum signed 32 bit value */
#define _UI32_MAX     0xffffffffui32 /* maximum unsigned 32 bit value */
#endif

#if     _INTEGRAL_MAX_BITS >= 64
/* minimum signed 64 bit value */
#define _I64_MIN    (-9223372036854775807i64 - 1)
/* maximum signed 64 bit value */
#define _I64_MAX    9223372036854775807i64
/* maximum unsigned 64 bit value */
#define _UI64_MAX     0xffffffffffffffffui64
#endif

#if     _INTEGRAL_MAX_BITS >= 128
/* minimum signed 128 bit value */
#define _I128_MIN   (-170141183460469231731687303715884105727i128 - 1)
/* maximum signed 128 bit value */
#define _I128_MAX     170141183460469231731687303715884105727i128
/* maximum unsigned 128 bit value */
#define _UI128_MAX    0xffffffffffffffffffffffffffffffffui128
#endif

Professionele website nodig?


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18-09 18:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op zondag 07 oktober 2001 17:59 schreef mietje het volgende:

[..]

Ok, maar hoe zit het dan met:
[..]

Hier pad je dus wel degelijk om de size van de struct te alignen, er is voor de rest geen enkele noodzaak om er een loos byte achter te plakken.
ja je hebt gelijk, mijn uitleg was een beetje krom, heb ik wel vaker last van :)

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