SizeOf/fi: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: SizeOf/fi
| Old | New | Line | |
|---|---|---|---|
| 1 | + | [[Compile time/fi|Käännösaikainen]] [[Function/fi|funktio]] [`SizeOf`](https://www.freepascal.org/docs-html/rtl/system/sizeof.html) arvioi tietyn [[Data type/fi|tyyppisen]] nimen tai [[Variable/fi|muuttujan]] [[Identifier/fi|tunnisteen]] koon tavuina (byte). | |
| 2 | + | ||
| 3 | + | `sizeOf` voi olla myös käännösaikaisissa laajennuksissa, kuten [[Compiler directive|kääntäjädirektiiveissä]]. | |
| 4 | + | ||
| 5 | + | ## Käyttö | |
| 6 | + | ||
| 7 | + | `SizeOf` esiintyy erityisesti [[Assembler/fi|assembly-kielessä]] tai kun suoritetaan muistin manuaalista allokointia: | |
| 8 | + | ||
| 9 | + | ``` pascal | |
| 10 | + | program sizeOfDemo(input, output, stderr); | |
| 11 | + | ||
| 12 | + | {$typedAddress on} | |
| 13 | + | ||
| 14 | + | uses | |
| 15 | + | heaptrc; | |
| 16 | + | ||
| 17 | + | type | |
| 18 | + | s = record | |
| 19 | + | c: char; | |
| 20 | + | i: longint; | |
| 21 | + | end; | |
| 22 | + | ||
| 23 | + | var | |
| 24 | + | x: ^s; | |
| 25 | + | ||
| 26 | + | begin | |
| 27 | + | returnNilIfGrowHeapFails := true; | |
| 28 | + | ||
| 29 | + | getMem(x, sizeOf(x)); | |
| 30 | + | ||
| 31 | + | if not assigned(x) then | |
| 32 | + | begin | |
| 33 | + | writeLn(stderr, 'malloc for x failed'); | |
| 34 | + | halt(1); | |
| 35 | + | end; | |
| 36 | + | ||
| 37 | + | x^.c := 'r'; | |
| 38 | + | x^.i := -42; | |
| 39 | + | ||
| 40 | + | freeMem(x, sizeOf(x)); | |
| 41 | + | end. | |
| 42 | + | ``` | |
| 43 | + | ||
| 44 | + | Rakenteellisten tietotyyppien suora käsittely assembly-kielellä edellyttää myös tietojen (datan) koon tuntemusta: | |
| 45 | + | ||
| 46 | + | ``` pascal | |
| 47 | + | program sizeOfDemo(input, output, stderr); | |
| 48 | + | ||
| 49 | + | type | |
| 50 | + | integerArray = array of integer; | |
| 51 | + | ||
| 52 | + | function sum(const f: integerArray): int64; | |
| 53 | + | {$ifdef CPUx86_64} | |
| 54 | + | assembler; | |
| 55 | + | {$asmMode intel} | |
| 56 | + | asm | |
| 57 | + | // ensure f is in a particular register | |
| 58 | + | mov rsi, f // rsi := f (pointer to an array) | |
| 59 | + | ||
| 60 | + | // check for nil pointer (i.e. empty array) | |
| 61 | + | test rsi, rsi // rsi = 0 ? | |
| 62 | + | jz @sum_abort // if rsi = nil then goto abort | |
| 63 | + | ||
| 64 | + | // load last index of array [theoretically there is highF] | |
| 65 | + | mov rcx, [rsi] - sizeOf(sizeInt) // rcx := (rsi - sizeOf(sizeInt))^ | |
| 66 | + | ||
| 67 | + | // load first element, since loop condition won't reach it | |
| 68 | + | {$if sizeOf(integer) = 4} | |
| 69 | + | mov eax, [rsi] // eax := rsi^ | |
| 70 | + | {$elseif sizeOf(integer) = 2} | |
| 71 | + | mov ax, [rsi] // ax := rsi^ | |
| 72 | + | {$else} {$error unexpected integer size} {$endif} | |
| 73 | + | ||
| 74 | + | // we're done, if f doesn't contain any more elements | |
| 75 | + | test rcx, rcx // rcx = 0 ? | |
| 76 | + | jz @sum_done // if high(f) = 0 then goto done | |
| 77 | + | ||
| 78 | + | @sum_iterate: | |
| 79 | + | {$if sizeOf(integer) = 4} | |
| 80 | + | mov edx, [rsi + rcx * 4] // edx := (rsi + 4 * rcx)^ | |
| 81 | + | {$elseif sizeOf(integer) = 2} | |
| 82 | + | mov dx, [rsi + rcx * 2] // dx := (rsi + 2 * rcx)^ | |
| 83 | + | {$else} {$error unexpected scale factor} {$endif} | |
| 84 | + | ||
| 85 | + | add rax, rdx // rax := rax + rdx | |
| 86 | + | ||
| 87 | + | jo @sum_abort // if OF then goto abort | |
| 88 | + | ||
| 89 | + | loop @sum_iterate // dec(rcx) | |
| 90 | + | // if rcx <> 0 then goto iterate | |
| 91 | + | ||
| 92 | + | jmp @sum_done // goto done | |
| 93 | + | ||
| 94 | + | @sum_abort: | |
| 95 | + | // load neutral element for addition | |
| 96 | + | xor rax, rax // rax := 0 | |
| 97 | + | ||
| 98 | + | @sum_done: | |
| 99 | + | end; | |
| 100 | + | {$else} | |
| 101 | + | unimplemented; | |
| 102 | + | begin | |
| 103 | + | sum := 0; | |
| 104 | + | end; | |
| 105 | + | {$endif} | |
| 106 | + | ||
| 107 | + | begin | |
| 108 | + | writeLn(sum(integerArray.create(2, 5, 11, 17, 23))); | |
| 109 | + | end. | |
| 110 | + | ``` | |
| 111 | + | ||
| 112 | + | [[FPC]]:llä [`integer`](https://www.freepascal.org/docs-html/rtl/system/integer.html) kokonaisluvun koko riippuu käytetystä [[Compiler Mode/fi|kääntäjän moodista]]. `SizeOf(sizeInt)` lisättiin kuitenkin vain esittelyä varten. `{$ifdef CPUx86_64}` haarassa `sizeOf(sizeInt)` on aina `8`. | |
| 113 | + | ||
| 114 | + | ## Vertailevia huomautuksia | |
| 115 | + | ||
| 116 | + | ### Dynaamiset taulukot ja vastaavat | |
| 117 | + | ||
| 118 | + | Koska[[Dynamic array|dynaamiset taulukot]] toteutetaan osoittimina are realized as pointers to a block on the heap, `sizeOf` arvioi osoittimen koon. Dynaamisen taulukon koon määrittämiseksi. `SizeOf` on käytettävä yhdessä funktion [`length`](https://www.freepascal.org/docs-html/rtl/system/length.html) kanssa. | |
| 119 | + | ||
| 120 | + | ``` pascal | |
| 121 | + | program dynamicArraySizeDemo(input, output, stderr); | |
| 122 | + | ||
| 123 | + | uses | |
| 124 | + | sysUtils; | |
| 125 | + | ||
| 126 | + | resourcestring | |
| 127 | + | enteredN = 'You''ve entered %0:d integers'; | |
| 128 | + | totalData = 'occupying a total of %0:d Bytes.'; | |
| 129 | + | ||
| 130 | + | var | |
| 131 | + | f: array of longint; | |
| 132 | + | ||
| 133 | + | begin | |
| 134 | + | setLength(f, 0); | |
| 135 | + | ||
| 136 | + | while not eof() do | |
| 137 | + | begin | |
| 138 | + | setLength(f, length(f) + 1); | |
| 139 | + | readLn(f[length(f)]); | |
| 140 | + | end; | |
| 141 | + | ||
| 142 | + | writeLn(format(enteredN, [length(f)])); | |
| 143 | + | writeLn(format(totalData, [length(f) * sizeOf(f[0])])); | |
| 144 | + | end. | |
| 145 | + | ``` | |
| 146 | + | ||
| 147 | + | Lähestymistapa on sama [[Ansistring|ANSI strings]] merkkijonoille (riippuen myös `{$longstrings}` kääntäjän kytkimen tilasta, jota merkitään myös [[String|string]]). Ei saa unohtaa, että dynaamisissa taulukoissa on hallintatiedot viitatun hyötykuorman edessä. Joten jos todella halutaan tietää, kuinka paljon muistia on varattu yhdelle taulukolla, niin on otettava huomioon myös suurin (viimeinen indeksi taulukossa) ja viitearvojen kentät. | |
| 148 | + | ||
| 149 | + | ### Luokat | |
| 150 | + | ||
| 151 | + | [[Class/fi|Luokat (class)]] ovat myös viitteitä. Luokka [`TObject`](https://www.freepascal.org/docs-html/rtl/system/tobject.html) tarjoaa funktion [`instanceSize`](https://www.freepascal.org/docs-html/rtl/system/tobject.instancesize.html). Se palauttaa olion koon, koska se määräytyy luokan tyypin määritelmän mukaan. Lisämuistia, jota [[Constructor/fi|rakentajat (constructor)]] ovat käyttäneet tai mikä tahansa [[Method/fi|metodi]], ei oteta huomioon. Huomaa, että luokat voivat sisältää myös dynaamisia taulukoita tai ANSI-merkkijonoja. | |
| 152 | + | ||
| 153 | + | --- | |
| 154 | + | *From the Free Pascal wiki, page "SizeOf/fi", as it stood on 2022-08-06 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
