Difference between revisions of "SizeOf/ru"
(Created page with "{{SizeOf}} The compile-time function {{Doc|package=RTL|unit=system|identifier=sizeof|text=<syntaxhighlight lang="pascal" enclose="none">sizeOf<...") |
|||
(5 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
{{SizeOf}} | {{SizeOf}} | ||
+ | [[Function/ru|Функция]] [[Compile_time|времени компиляции]] {{Doc|package=RTL|unit=system|identifier=sizeof|text=<syntaxhighlight lang="pascal" inline>sizeOf</syntaxhighlight>}} вычисляет размер в байтах данного имени [[Data_type/ru|типа данных]] или [[Identifier/ru|идентификатора]] [[Variable/ru|переменной]]. | ||
− | + | <syntaxhighlight lang="pascal" inline>sizeOf</syntaxhighlight> также может применяться в выражениях времени компиляции внутри [[Compiler_directive|директив компилятора]]. | |
− | |||
− | == | + | __TOC__ |
− | <syntaxhighlight lang="pascal" | + | |
+ | == Использование == | ||
+ | |||
+ | <syntaxhighlight lang="pascal" inline>sizeOf</syntaxhighlight> особенно часто встречается в [[Assembler| ассемблере]] или при ручном выделении памяти: | ||
<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 42: | Line 45: | ||
end. | end. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Прямая обработка структурированных типов данных на ассемблере также требует знания размеров данных: | |
<syntaxhighlight lang="pascal" line highlight="19,22,24,33,35"> | <syntaxhighlight lang="pascal" line highlight="19,22,24,33,35"> | ||
program sizeOfDemo(input, output, stderr); | program sizeOfDemo(input, output, stderr); | ||
Line 54: | Line 57: | ||
{$asmMode intel} | {$asmMode intel} | ||
asm | asm | ||
− | // | + | // убеждаемся, что f находится в конкретном регистре |
− | mov rsi, f // rsi := f ( | + | mov rsi, f // rsi := f (указатель на массив) |
− | // | + | // проверка на пустой (nil) указатель (напр. пустой массив) |
test rsi, rsi // rsi = 0 ? | test rsi, rsi // rsi = 0 ? | ||
− | jz @sum_abort // | + | jz @sum_abort // если rsi = nil, то переходим к @sum_abort |
− | // | + | // загружаем последний индекс массива [теоретически это верхний элемент массива F] |
mov rcx, [rsi] - sizeOf(sizeInt) // rcx := (rsi - sizeOf(sizeInt))^ | mov rcx, [rsi] - sizeOf(sizeInt) // rcx := (rsi - sizeOf(sizeInt))^ | ||
− | // | + | // загружаем первый элемент, поскольку условие цикла не дойдет до него |
{$if sizeOf(integer) = 4} | {$if sizeOf(integer) = 4} | ||
mov eax, [rsi] // 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 | + | {$else} {$error неожиданный целочисленный размер} {$endif} |
− | // | + | // мы сделаем, если f не содержит больше элементов |
test rcx, rcx // rcx = 0 ? | test rcx, rcx // rcx = 0 ? | ||
− | jz @sum_done // | + | jz @sum_done // если high(f) = 0, то переходим к @sum_done |
@sum_iterate: | @sum_iterate: | ||
Line 80: | Line 83: | ||
{$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)^ | ||
− | {$else} {$error | + | {$else} {$error неожиданный масштабный коэффициент} {$endif} |
add rax, rdx // rax := rax + rdx | add rax, rdx // rax := rax + rdx | ||
− | jo @sum_abort // | + | jo @sum_abort // если OF, то переходим к @sum_abort |
loop @sum_iterate // dec(rcx) | loop @sum_iterate // dec(rcx) | ||
− | // | + | // если rcx <> 0, то переходим к @sum_iterate |
− | jmp @sum_done // | + | jmp @sum_done // переходим к @sum_done |
@sum_abort: | @sum_abort: | ||
− | // | + | // загружаем нейтральный элемент для прибавления |
xor rax, rax // rax := 0 | xor rax, rax // rax := 0 | ||
Line 108: | Line 111: | ||
end. | end. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | |||
− | |||
− | == | + | В [[FPC/ru|FPC]] размер {{Doc|package=RTL|unit=system|identifier=integer|text=<syntaxhighlight lang="pascal" inline>integer</syntaxhighlight>}} зависит от используемого [[Compiler_Mode|режима компилятора]]. |
− | = | + | Однако <syntaxhighlight lang="pascal" inline>sizeOf(sizeInt)</syntaxhighlight> был вставлен только для демонстрационных целей. В ветке <syntaxhighlight lang="pascal" inline>{$ifdef CPUx86_64}</syntaxhighlight> <syntaxhighlight lang="pascal" inline>sizeOf(sizeInt)</syntaxhighlight> всегда равен <syntaxhighlight lang="pascal" inline>8</syntaxhighlight>. |
− | + | ||
− | + | == Сравнительные замечания == | |
+ | === Динамические массивы и тому подобное === | ||
+ | Поскольку [[Dynamic_array/ru|динамические массивы]] реализованы как указатели на блок в куче, <tt>sizeOf</tt> оценивает размер указателя. Чтобы определить размер массива - его данных - необходимо использовать <tt>sizeOf</tt> вместе с функцией {{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 123: | Line 126: | ||
resourcestring | resourcestring | ||
− | enteredN = ' | + | enteredN = 'Вы ввели %0:d целых чисел'; |
− | totalData = ' | + | totalData = 'занимающих всего %0:d Bytes.'; |
var | var | ||
Line 142: | Line 145: | ||
end. | end. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | |||
− | |||
− | === | + | Подход аналогичен для [[Ansistring|ANSI strings]] (в зависимости от состояния переключателя компилятора <syntaxhighlight lang="pascal" inline>{$longstrings}</syntaxhighlight>, возможно, также обозначаемого [[String/ru|<syntaxhighlight lang="pascal" inline>string</syntaxhighlight>]]). Не забывайте, что динамические массивы управляют данными перед ссылочным блоком полезной нагрузки. Поэтому, если вы действительно хотите знать, сколько памяти было зарезервировано для одного массива, вам также нужно будет учитывать [индекс массива] high (последний индекс в массиве) и счетчик ссылок. |
− | [[Class| | + | |
− | + | === Классы === | |
− | + | [[Class/ru|Классы]] также являются указателями. | |
− | + | Класс {{Doc|package=RTL|unit=system|identifier=tobject|text=<syntaxhighlight lang="pascal" inline>TObject</syntaxhighlight>}} предоставляет функцию {{Doc|package=RTL|unit=system|identifier=tobject.instancesize|text=<syntaxhighlight lang="pascal" inline>instanceSize</syntaxhighlight>}}. Он возвращает размер объекта, как это предписывается определением типа класса. Дополнительная память, которая выделяется [[Constructor/ru|конструктором]] или любым другим [[Method|методом]], не учитывается. Обратите внимание, что классы также могут содержать динамические массивы или строки ANSI. | |
− |
Latest revision as of 17:21, 6 August 2022
│
Deutsch (de) │
English (en) │
suomi (fi) │
русский (ru) │
Функция времени компиляции sizeOf
вычисляет размер в байтах данного имени типа данных или идентификатора переменной.
sizeOf
также может применяться в выражениях времени компиляции внутри директив компилятора.
Использование
sizeOf
особенно часто встречается в ассемблере или при ручном выделении памяти:
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.
Прямая обработка структурированных типов данных на ассемблере также требует знания размеров данных:
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 // убеждаемся, что f находится в конкретном регистре
12 mov rsi, f // rsi := f (указатель на массив)
13
14 // проверка на пустой (nil) указатель (напр. пустой массив)
15 test rsi, rsi // rsi = 0 ?
16 jz @sum_abort // если rsi = nil, то переходим к @sum_abort
17
18 // загружаем последний индекс массива [теоретически это верхний элемент массива F]
19 mov rcx, [rsi] - sizeOf(sizeInt) // rcx := (rsi - sizeOf(sizeInt))^
20
21 // загружаем первый элемент, поскольку условие цикла не дойдет до него
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 неожиданный целочисленный размер} {$endif}
27
28 // мы сделаем, если f не содержит больше элементов
29 test rcx, rcx // rcx = 0 ?
30 jz @sum_done // если high(f) = 0, то переходим к @sum_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 неожиданный масштабный коэффициент} {$endif}
38
39 add rax, rdx // rax := rax + rdx
40
41 jo @sum_abort // если OF, то переходим к @sum_abort
42
43 loop @sum_iterate // dec(rcx)
44 // если rcx <> 0, то переходим к @sum_iterate
45
46 jmp @sum_done // переходим к @sum_done
47
48@sum_abort:
49 // загружаем нейтральный элемент для прибавления
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.
В FPC размер integer
зависит от используемого режима компилятора.
Однако sizeOf(sizeInt)
был вставлен только для демонстрационных целей. В ветке {$ifdef CPUx86_64}
sizeOf(sizeInt)
всегда равен 8
.
Сравнительные замечания
Динамические массивы и тому подобное
Поскольку динамические массивы реализованы как указатели на блок в куче, sizeOf оценивает размер указателя. Чтобы определить размер массива - его данных - необходимо использовать sizeOf вместе с функцией length
1program dynamicArraySizeDemo(input, output, stderr);
2
3uses
4 sysUtils;
5
6resourcestring
7 enteredN = 'Вы ввели %0:d целых чисел';
8 totalData = 'занимающих всего %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.
Подход аналогичен для ANSI strings (в зависимости от состояния переключателя компилятора {$longstrings}
, возможно, также обозначаемого string
). Не забывайте, что динамические массивы управляют данными перед ссылочным блоком полезной нагрузки. Поэтому, если вы действительно хотите знать, сколько памяти было зарезервировано для одного массива, вам также нужно будет учитывать [индекс массива] high (последний индекс в массиве) и счетчик ссылок.
Классы
Классы также являются указателями.
Класс TObject
предоставляет функцию instanceSize
. Он возвращает размер объекта, как это предписывается определением типа класса. Дополнительная память, которая выделяется конструктором или любым другим методом, не учитывается. Обратите внимание, что классы также могут содержать динамические массивы или строки ANSI.