Sign in Join
Wiki copytemporary

SizeOf: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: SizeOf

OldNewLine
1+The [[Compile time|compile-time]] [[Function|function]] [`sizeOf`](https://www.freepascal.org/docs-html/rtl/system/sizeof.html) evaluates to the size in Bytes of a given [[Data type|data type]] name or [[Variable|variable]] [[Identifier|identifier]].
2+
3+`sizeOf` can appear in compile-time expressions, inside [[Compiler directive|compiler directives]], too.
4+
5+## usage
6+
7+`sizeOf` is especially encountered in [[Assembler|assembly language]] or when doing manual allocation of memory:
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+Direct handling of structured data types in assembly language requires awareness of data sizes, too:
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+With [[FPC]] the size of an [`integer`](https://www.freepascal.org/docs-html/rtl/system/integer.html) depends on the used [[Compiler Mode|compiler mode]]. However, `sizeOf(sizeInt)` was inserted for demonstration purposes only. In the `{$ifdef CPUx86_64}` branch `sizeOf(sizeInt)` is always `8`.
113+
114+## comparative remarks
115+
116+### dynamic arrays and alike
117+
118+Since [[Dynamic array|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`](https://www.freepascal.org/docs-html/rtl/system/length.html).
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+The approach is the same for [[Ansistring|ANSI strings]] (depending on the `{$longstrings}` compiler switch state possibly denoted by [[String|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.
148+
149+### classes
150+
151+[[Class|Classes]] as well are pointers. The class [`TObject`](https://www.freepascal.org/docs-html/rtl/system/tobject.html) provides the function [`instanceSize`](https://www.freepascal.org/docs-html/rtl/system/tobject.instancesize.html). It returns an object's size as it is determined by the class's type definition. Additional memory that's allocated by [[Constructor|constructors]] or any [[Method|method]], is not taken into account. Note, that classes might contain dynamic arrays or ANSI strings, too.
152+
153+## see also
154+
155+- [article “`sizeOf`” in the English Wikipedia](https://en.wikipedia.org/wiki/Sizeof) (primarily about C’s unary operator)
156+
157+---
158+*From the Free Pascal wiki, page "SizeOf", 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).*

Back to history