Difference between revisions of "SizeOf"
(add Category:Code) |
|||
(11 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | {{ | + | {{SizeOf}} |
− | |||
− | <syntaxhighlight lang="pascal" | + | |
+ | The [[Compile time|compile-time]] [[Function|function]] {{Doc|package=RTL|unit=system|identifier=sizeof|text=<syntaxhighlight lang="pascal" inline>sizeOf</syntaxhighlight>}} evaluates to the size in Bytes of a given [[Data type|data type]] name or [[Variable|variable]] [[Identifier|identifier]]. | ||
+ | |||
+ | <syntaxhighlight lang="pascal" inline>sizeOf</syntaxhighlight> can appear in compile-time expressions, inside [[Compiler directive|compiler directives]], too. | ||
== usage == | == usage == | ||
− | <syntaxhighlight lang="pascal" | + | <syntaxhighlight lang="pascal" inline>sizeOf</syntaxhighlight> is especially encountered in [[Assembler|assembly language]] or when doing manual allocation of memory: |
<syntaxhighlight lang="pascal" line highlight="20,31"> | <syntaxhighlight lang="pascal" line highlight="20,31"> | ||
program sizeOfDemo(input, output, stderr); | program sizeOfDemo(input, output, stderr); | ||
Line 41: | Line 43: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Direct handling of structured data types in assembly language requires awareness of data sizes, too: | Direct handling of structured data types in assembly language requires awareness of data sizes, too: | ||
− | <syntaxhighlight lang="pascal" line highlight=" | + | <syntaxhighlight lang="pascal" line highlight="19,22,24,33,35"> |
program sizeOfDemo(input, output, stderr); | program sizeOfDemo(input, output, stderr); | ||
− | function sum(const f: | + | type |
+ | integerArray = array of integer; | ||
+ | |||
+ | function sum(const f: integerArray): int64; | ||
{$ifdef CPUx86_64} | {$ifdef CPUx86_64} | ||
assembler; | assembler; | ||
Line 61: | Line 66: | ||
// load first element, since loop condition won't reach it | // load first element, since loop condition won't reach it | ||
{$if sizeOf(integer) = 4} | {$if sizeOf(integer) = 4} | ||
− | mov eax, [rsi] // | + | mov eax, [rsi] // eax := rsi^ |
{$elseif sizeOf(integer) = 2} | {$elseif sizeOf(integer) = 2} | ||
mov ax, [rsi] // ax := rsi^ | mov ax, [rsi] // ax := rsi^ | ||
{$else} {$error unexpected integer size} {$endif} | {$else} {$error unexpected integer size} {$endif} | ||
+ | |||
+ | // we're done, if f doesn't contain any more elements | ||
+ | test rcx, rcx // rcx = 0 ? | ||
+ | jz @sum_done // if high(f) = 0 then goto done | ||
@sum_iterate: | @sum_iterate: | ||
{$if sizeOf(integer) = 4} | {$if sizeOf(integer) = 4} | ||
− | mov edx, [rsi + rcx * 4] // | + | mov edx, [rsi + rcx * 4] // edx := (rsi + 4 * rcx)^ |
{$elseif sizeOf(integer) = 2} | {$elseif sizeOf(integer) = 2} | ||
− | mov dx, [rsi + rcx * 2] // dx := (rsi + 2 * | + | mov dx, [rsi + rcx * 2] // dx := (rsi + 2 * rcx)^ |
{$else} {$error unexpected scale factor} {$endif} | {$else} {$error unexpected scale factor} {$endif} | ||
Line 80: | Line 89: | ||
// if rcx <> 0 then goto iterate | // if rcx <> 0 then goto iterate | ||
− | + | jmp @sum_done // goto done | |
− | |||
@sum_abort: | @sum_abort: | ||
Line 95: | Line 103: | ||
end; | end; | ||
{$endif} | {$endif} | ||
− | |||
− | |||
− | |||
begin | begin | ||
− | + | writeLn(sum(integerArray.create(2, 5, 11, 17, 23))); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end. | end. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | With [[FPC]] the size of an {{Doc|package=RTL|unit=system|identifier=integer|text=<syntaxhighlight lang="pascal" inline>integer</syntaxhighlight>}} depends on the used [[Compiler Mode|compiler mode]]. | ||
+ | However, <syntaxhighlight lang="pascal" inline>sizeOf(sizeInt)</syntaxhighlight> was inserted for demonstration purposes only. | ||
+ | In the <syntaxhighlight lang="pascal" inline>{$ifdef CPUx86_64}</syntaxhighlight> branch <syntaxhighlight lang="pascal" inline>sizeOf(sizeInt)</syntaxhighlight> is always <syntaxhighlight lang="pascal" inline>8</syntaxhighlight>. | ||
== comparative remarks == | == comparative remarks == | ||
=== dynamic arrays and alike === | === dynamic arrays and alike === | ||
− | Since [[Dynamic array|dynamic arrays]] are realized as pointers to a block on the heap, <syntaxhighlight lang="pascal" | + | Since [[Dynamic array|dynamic arrays]] are realized as pointers to a block on the heap, <syntaxhighlight lang="pascal" inline>sizeOf</syntaxhighlight> evaluates to the pointer's size. |
− | In order to determine the array's | + | In order to determine the array's size – of its data – <syntaxhighlight lang="pascal" inline>sizeOf</syntaxhighlight> has to be used in conjunction with the function {{Doc|package=RTL|unit=system|identifier=length|text=<syntaxhighlight lang="pascal" inline>length</syntaxhighlight>}}. |
<syntaxhighlight lang="pascal" line highlight="23"> | <syntaxhighlight lang="pascal" line highlight="23"> | ||
program dynamicArraySizeDemo(input, output, stderr); | program dynamicArraySizeDemo(input, output, stderr); | ||
Line 140: | Line 142: | ||
end. | end. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | The approach is the same for [[Ansistring|ANSI strings]] (depending on the <syntaxhighlight lang="pascal" | + | The approach is the same for [[Ansistring|ANSI strings]] (depending on the <syntaxhighlight lang="pascal" inline>{$longstrings}</syntaxhighlight> compiler switch state possibly denoted by [[String|<syntaxhighlight lang="pascal" inline>string</syntaxhighlight>]], too). |
+ | Do not forget that dynamic arrays have management data in front of the referenced payload block. | ||
+ | So if you ''really'' want to know, how much memory has been reserved for one array, you would have to take the high (last index in array) and reference count fields into account, too. | ||
=== classes === | === classes === | ||
− | Classes as well are pointers. | + | [[Class|Classes]] as well are pointers. |
− | The class {{Doc|package=RTL|unit=system|identifier=tobject|text=<syntaxhighlight lang="pascal" | + | The class {{Doc|package=RTL|unit=system|identifier=tobject|text=<syntaxhighlight lang="pascal" inline>TObject</syntaxhighlight>}} provides the function {{Doc|package=RTL|unit=system|identifier=tobject.instancesize|text=<syntaxhighlight lang="pascal" inline>instanceSize</syntaxhighlight>}}. |
It returns an object's size as it is determined by the class's type definition. | It returns an object's size as it is determined by the class's type definition. | ||
− | Additional memory that's allocated by constructors or any method, is not taken into account. | + | Additional memory that's allocated by [[Constructor|constructors]] or any [[Method|method]], is not taken into account. |
− | Note, classes might contain dynamic arrays or ANSI strings, too. | + | Note, that classes might contain dynamic arrays or ANSI strings, too. |
− | [ | + | == see also == |
+ | * [https://en.wikipedia.org/wiki/Sizeof article “<code>sizeOf</code>” in the English Wikipedia] (primarily about C’s unary operator) |
Latest revision as of 17:26, 6 August 2022
│
Deutsch (de) │
English (en) │
suomi (fi) │
русский (ru) │
The compile-time function sizeOf
evaluates to the size in Bytes of a given data type name or variable identifier.
sizeOf
can appear in compile-time expressions, inside compiler directives, too.
usage
sizeOf
is especially encountered in assembly language or when doing manual allocation of memory:
1program sizeOfDemo(input, output, stderr);
2
3{$typedAddress on}
4
5uses
6 heaptrc;
7
8type
9 s = record
10 c: char;
11 i: longint;
12 end;
13
14var
15 x: ^s;
16
17begin
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));
32end.
Direct handling of structured data types in assembly language requires awareness of data sizes, too:
1program sizeOfDemo(input, output, stderr);
2
3type
4 integerArray = array of integer;
5
6function sum(const f: integerArray): int64;
7{$ifdef CPUx86_64}
8assembler;
9{$asmMode intel}
10asm
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:
53end;
54{$else}
55unimplemented;
56begin
57 sum := 0;
58end;
59{$endif}
60
61begin
62 writeLn(sum(integerArray.create(2, 5, 11, 17, 23)));
63end.
With FPC the size of an integer
depends on the used compiler mode.
However, sizeOf(sizeInt)
was inserted for demonstration purposes only.
In the {$ifdef CPUx86_64}
branch sizeOf(sizeInt)
is always 8
.
comparative remarks
dynamic arrays and alike
Since dynamic arrays are realized as pointers to a block on the heap, sizeOf
evaluates to the pointer's size.
In order to determine the array's size – of its data – sizeOf
has to be used in conjunction with the function length
.
1program dynamicArraySizeDemo(input, output, stderr);
2
3uses
4 sysUtils;
5
6resourcestring
7 enteredN = 'You''ve entered %0:d integers';
8 totalData = 'occupying a total of %0:d Bytes.';
9
10var
11 f: array of longint;
12
13begin
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])]));
24end.
The approach is the same for ANSI strings (depending on the {$longstrings}
compiler switch state possibly denoted by string
, too).
Do not forget that dynamic arrays have management data in front of the referenced payload block.
So if you really want to know, how much memory has been reserved for one array, you would have to take the high (last index in array) and reference count fields into account, too.
classes
Classes as well are pointers.
The class TObject
provides the function instanceSize
.
It returns an object's size as it is determined by the class's type definition.
Additional memory that's allocated by constructors or any method, is not taken into account.
Note, that classes might contain dynamic arrays or ANSI strings, too.
see also
- article “
sizeOf
” in the English Wikipedia (primarily about C’s unary operator)