SizeOf/fi

From Free Pascal wiki

Deutsch (de) English (en) suomi (fi) русский (ru)


Käännösaikainen funktio SizeOf arvioi tietyn tyyppisen nimen tai muuttujan tunnisteen koon tavuina (byte).

sizeOf voi olla myös käännösaikaisissa laajennuksissa, kuten kääntäjädirektiiveissä.

Käyttö

SizeOf esiintyy erityisesti assembly-kielessä tai kun suoritetaan muistin manuaalista allokointia:

 1 program sizeOfDemo(input, output, stderr);
 2 
 3 {$typedAddress on}
 4 
 5 uses
 6 	heaptrc;
 7 
 8 type
 9 	s = record
10 		c: char;
11 		i: longint;
12 	end;
13 
14 var
15 	x: ^s;
16 
17 begin
18 	returnNilIfGrowHeapFails := true;
19 	
20 	getMem(x, sizeOf(x));
21 	
22 	if not assigned(x) then
23 	begin
24 		writeLn(stderr, 'malloc for x failed');
25 		halt(1);
26 	end;
27 	
28 	x^.c := 'r';
29 	x^.i := -42;
30 	
31 	freeMem(x, sizeOf(x));
32 end.

Rakenteellisten tietotyyppien suora käsittely assembly-kielellä edellyttää myös tietojen (datan) koon tuntemusta:

 1 program sizeOfDemo(input, output, stderr);
 2 
 3 type
 4 	integerArray = array of integer;
 5 
 6 function sum(const f: integerArray): int64;
 7 {$ifdef CPUx86_64}
 8 assembler;
 9 {$asmMode intel}
10 asm
11 	// ensure f is in a particular register
12 	mov rsi, f                       // rsi := f  (pointer to an array)
13 	
14 	// check for nil pointer (i.e. empty array)
15 	test rsi, rsi                    // rsi = 0 ?
16 	jz @sum_abort                    // if rsi = nil then goto abort
17 	
18 	// load last index of array [theoretically there is highF]
19 	mov rcx, [rsi] - sizeOf(sizeInt) // rcx := (rsi - sizeOf(sizeInt))^
20 	
21 	// load first element, since loop condition won't reach it
22 	{$if sizeOf(integer) = 4}
23 	mov eax, [rsi]                   // eax := rsi^
24 	{$elseif sizeOf(integer) = 2}
25 	mov ax, [rsi]                    // ax := rsi^
26 	{$else} {$error unexpected integer size} {$endif}
27 	
28 	// we're done, if f doesn't contain any more elements
29 	test rcx, rcx                    // rcx = 0 ?
30 	jz @sum_done                     // if high(f) = 0 then goto done
31 	
32 @sum_iterate:
33 	{$if sizeOf(integer) = 4}
34 	mov edx, [rsi + rcx * 4]         // edx := (rsi + 4 * rcx)^
35 	{$elseif sizeOf(integer) = 2}
36 	mov dx, [rsi + rcx * 2]          // dx := (rsi + 2 * rcx)^
37 	{$else} {$error unexpected scale factor} {$endif}
38 	
39 	add rax, rdx                     // rax := rax + rdx
40 	
41 	jo @sum_abort                    // if OF then goto abort
42 	
43 	loop @sum_iterate                // dec(rcx)
44 	                                 // if rcx <> 0 then goto iterate
45 	
46 	jmp @sum_done                    // goto done
47 	
48 @sum_abort:
49 	// load neutral element for addition
50 	xor rax, rax                     // rax := 0
51 	
52 @sum_done:
53 end;
54 {$else}
55 unimplemented;
56 begin
57 	sum := 0;
58 end;
59 {$endif}
60 
61 begin
62 	writeLn(sum(integerArray.create(2, 5, 11, 17, 23)));
63 end.

FPC:llä integer kokonaisluvun koko riippuu käytetystä kääntäjän moodista. SizeOf(sizeInt) lisättiin kuitenkin vain esittelyä varten. {$ifdef CPUx86_64} haarassa sizeOf(sizeInt) on aina 8.

Vertailevia huomautuksia

Dynaamiset taulukot ja vastaavat

Koskadynaamiset 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 kanssa.

 1 program dynamicArraySizeDemo(input, output, stderr);
 2 
 3 uses
 4 	sysUtils;
 5 
 6 resourcestring
 7 	enteredN = 'You''ve entered %0:d integers';
 8 	totalData = 'occupying a total of %0:d Bytes.';
 9 
10 var
11 	f: array of longint;
12 
13 begin
14 	setLength(f, 0);
15 	
16 	while not eof() do
17 	begin
18 		setLength(f, length(f) + 1);
19 		readLn(f[length(f)]);
20 	end;
21 	
22 	writeLn(format(enteredN, [length(f)]));
23 	writeLn(format(totalData, [length(f) * sizeOf(f[0])]));
24 end.

Lähestymistapa on sama ANSI strings merkkijonoille (riippuen myös {$longstrings} kääntäjän kytkimen tilasta, jota merkitään myös 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.

Luokat

Luokat (class) ovat myös viitteitä. Luokka TObject tarjoaa funktion instanceSize. Se palauttaa olion koon, koska se määräytyy luokan tyypin määritelmän mukaan. Lisämuistia, jota rakentajat (constructor) ovat käyttäneet tai mikä tahansa metodi, ei oteta huomioon. Huomaa, että luokat voivat sisältää myös dynaamisia taulukoita tai ANSI-merkkijonoja.