SizeOf: Difference between revisions

From Free Pascal wiki
Jump to navigationJump to search
(→‎dynamic arrays and alike: management data)
m (→‎usage: comment revision)
Line 68: Line 68:
@sum_iterate:
@sum_iterate:
{$if sizeOf(integer) = 4}
{$if sizeOf(integer) = 4}
mov edx, [rsi + rcx * 4]        // rdx := (rsi + 4 * rcx)^
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 * rcx)^
mov dx, [rsi + rcx * 2]          // dx := (rsi + 2 * rcx)^

Revision as of 11:10, 16 May 2018

Template:Translate 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:

program sizeOfDemo(input, output, stderr);

{$typedAddress on}

uses
	heaptrc;

type
	s = record
		c: char;
		i: longint;
	end;

var
	x: ^s;

begin
	returnNilIfGrowHeapFails := true;
	
	getMem(x, sizeOf(x));
	
	if not assigned(x) then
	begin
		writeLn(stderr, 'malloc for x failed');
		halt(1);
	end;
	
	x^.c := 'r';
	x^.i := -42;
	
	freeMem(x, sizeOf(x));
end.

Direct handling of structured data types in assembly language requires awareness of data sizes, too:

program sizeOfDemo(input, output, stderr);

function sum(const f: array of integer): int64;
{$ifdef CPUx86_64}
assembler;
{$asmMode intel}
asm
	// ensure f is in a particular register
	mov rsi, f                       // rsi := f  (pointer to an array)
	
	// check for nil pointer (i.e. empty array)
	test rsi, rsi                    // rsi = 0 ?
	jz @sum_abort                    // if rsi = nil then goto abort
	
	// load last index of array [theoretically there is highF]
	mov rcx, [rsi] - sizeOf(sizeInt) // rcx := (rsi - sizeOf(sizeInt))^
	
	// load first element, since loop condition won't reach it
	{$if sizeOf(integer) = 4}
	mov eax, [rsi]                   // edx := rsi^
	{$elseif sizeOf(integer) = 2}
	mov ax, [rsi]                    // ax := rsi^
	{$else} {$error unexpected integer size} {$endif}
	
@sum_iterate:
	{$if sizeOf(integer) = 4}
	mov edx, [rsi + rcx * 4]         // edx := (rsi + 4 * rcx)^
	{$elseif sizeOf(integer) = 2}
	mov dx, [rsi + rcx * 2]          // dx := (rsi + 2 * rcx)^
	{$else} {$error unexpected scale factor} {$endif}
	
	add rax, rdx                     // rax := rax + rdx
	
	jo @sum_abort                    // if OF then goto abort
	
	loop @sum_iterate                // dec(rcx)
	                                 // if rcx <> 0 then goto iterate
	
	// TODO: j @done somehow compiles as jo @done
	jno @sum_done                    // goto done
	
@sum_abort:
	// load neutral element for addition
	xor rax, rax                     // rax := 0
	
@sum_done:
end;
{$else}
unimplemented;
begin
	sum := 0;
end;
{$endif}

var
	f: array of integer;

begin
	setLength(f, 5);
	f[0] := 2;
	f[1] := 5;
	f[2] := 11;
	f[3] := 17;
	f[4] := 23;
	writeLn(sum(f));
end.

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.

program dynamicArraySizeDemo(input, output, stderr);

uses
	sysUtils;

resourcestring
	enteredN = 'You''ve entered %0:d integers';
	totalData = 'occupying a total of %0:d Bytes.';

var
	f: array of longint;

begin
	setLength(f, 0);
	
	while not eof() do
	begin
		setLength(f, length(f) + 1);
		readLn(f[length(f)]);
	end;
	
	writeLn(format(enteredN, [length(f)]));
	writeLn(format(totalData, [length(f) * sizeOf(f[0])]));
end.

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.