Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.21.97.61] |
|
Сообщ.
#1
,
|
|
|
{$APPTYPE CONSOLE} {$A8} var X, Y: Byte; Z: record A, B: Byte end; begin with Z do WriteLn(Integer(@Y)-Integer(@X), ', ', Integer(@B)-Integer(@A)) end. Какой тогда толк от этого ключа ($A) и от слова "packed" ??? |
Сообщ.
#2
,
|
|
|
Jin X
Это обще принятое поведение. Наследует от архитектур где можно было читать только целыми слова кратными 16 бит или 32 бита. Соответственно эта граница и указывалась. В GPP ещё можно запретить переставлять поля. В x86 этот ключ используется для правильности работы InterLock - мьютексы, критические секции и так далее. Для них важно чтобы элементы не пересекали границу кэш линии. Packed однозначно сжимает. А алгоритм выравнивание описан в хэлпе. В двух словах для каждого типа используется своё выравнивание в зависимости от размера. А {A4} указывает максимальное значение как 4. TRec1= record A: Byte; B: DWord; end; TRec2= record A: DWord; B: Byte; end; Trec1 - будет расжатый, т.е размером 8 байт. А TRec2 5 байт. Вирт в своей книги пробовал объяснить сей странный алгоритм, но я так и не понял почему: Вирт Н.- Алгоритмы + структуры данных = программы. Мир (1985) |
Сообщ.
#3
,
|
|
|
Pavia, так я о том и говорю, что каждая переменная должна быть выровнена по границе 8 байт (т.к. указано A8). А по факту получается, что всё сжато: каждая байтовая переменная занимает 1 байт.
Цитата Jin X @ результатом должно быть 8, 8... Почему же по факту прога выдаёт 1, 1 ? Добавлено Вот Z4 работает нормально, а вот A4, A8 нет... как-то странно... |
Сообщ.
#4
,
|
|
|
default alignment = sizeOf(type) (simple types)
AX переопределяет выравнивание для полей sizeOf(field)>=X Type alignment masks |
Сообщ.
#5
,
|
|
|
Цитата Jin X @ так я о том и говорю, что каждая переменная должна быть выровнена по границе 8 байт (т.к. указано A8) Нет, ты говоришь о чем-то своем. Каждое поле выравнивается на свой собственный размер, если он не превышает значения указанного в опции $А. Т.е. $А не увеличивает границу выравнивания, а наоборот ограничивает ее, делает <= заданного значения. Поэтому $A8 используется по умолчанию и влияет только на выравнивание полей размером более 8 байт, а из простых типов это только extended. |
Сообщ.
#6
,
|
|
|
Всё, парни, спасибо. Перечитал на свежую голову, теперь всё ясно
p.s. Не совсем в тему, но set of забавный тип. Не занимает никогда 3 байта (т.е. только 1, 2, 4), зато может занимать 5, 6, 7(!) и т.д. прирост идёт по 1 байту (11 в т.ч.)... В Delphi7, по крайней мере... |
Сообщ.
#7
,
|
|
|
Цитата Jin X @ set of забавный тип. Не занимает никогда 3 байта (т.е. только 1, 2, 4), зато может занимать 5, 6, 7(!) и т.д. Это связано с тем, что множества размером до integer, могут хранится, передаваться и обрабатываться в регистрах процессора. Соотв-но и их размеры выравниваются на размеры доступных регистров. Если же размер больше integer, то используются операции с памятью с побайтовым доступом, поэтому выравнивание размера не обязательно. |
Сообщ.
#8
,
|
|
|
Ну тогда, согласись, и для 56 бит (7 байт) было бы проще сделать, например:
mov eax,[SrcVar] mov [DestVar],eax mov eax,[SrcVar+4] mov [DestVar+4],eax mov eax,[SrcVar] mov [DestVar],eax mov ax,[SrcVar+4] mov [DestVar+4],ax mov al,[SrcVar+6] mov [DestVar+6],al |
Сообщ.
#9
,
|
|
|
Цитата Jin X @ p.s. Не совсем в тему, но set of забавный тип. Не занимает никогда 3 байта (т.е. только 1, 2, 4), зато может занимать 5, 6, 7(!) и т.д. прирост идёт по 1 байту (11 в т.ч.)... сам тип никогда не будет занимать больше 4 байт. может иметь размер 1/2/4 (в структуре он может занимать 8 байт, но это обусловлено выравниванием самой структуры, а не типа данных) нюанс связан с самим типом. каждый элемент множества это бит. если у тебя до восьми значений в множестве type TEnum2 = (val1, val2); TSet2 = set of TEnum2; То он sizeof(TSet2) даст один байт. так как восьми битов хватит для харнения значений. если понадобится девять значений то размер вырастит к двум байтам. если понадобится 17 значений то размер сразу увеличится на 4 байта. это связано с архитектурой процессора x86. так как есть регистры al(1 байт)/ax(2 байта)/eax(4 байта) а трехбайтового регистра нет )) пс. размер типу моно навязать сразу через директиву {$Z4} и даже на два элемента он будет четырехбайтовый сам тип ограничен 256 элементами. по этой причине ему не нужно больше 4 байт, для хранения своих значений. так было как минимум с пятой версии (я думаю даже со второй.) искать информацию ко старым книгам и делать скрины мне лень (я ленивая скотина) пруф на текущую версию http://docwiki.embarcadero.com/RADStudio/B..._Types_(Delphi) пс. в отличии от старой документации в новых они некоторые вещи не документируют, но описание самых типов неплохое (они вроде только строки и массивы добротно задокументировали) Цитата Jin X @ Ну тогда, согласись, и для 56 бит (7 байт) было бы проще сделать, например: все что выбивается за рамки размера регистров используется через пень колоду. сам подумай сколько тебе нужно лишних манипуляций сделать что бы вычислить бит в третьем байте. если регистра трехбайтового у тебя нет. куда продуктивнее сразу использовать четырехбайтовый геристр |
Сообщ.
#10
,
|
|
|
Цитата Jin X @ Ну тогда, согласись, и для 56 бит (7 байт) было бы проще сделать Соглашусь. Конечно, на современных процессорах лучше выравнивать размер множества на 4 (тем более, что Intel предупреждает, что битовые операции bt\bts\btr, которые используются в операторах in\include\exclude, работают с 4-байтовыми порциями данных). Поэтому тут скорее дань традиции и пресловутой совместимости с древним турбо-паскалем, когда и bt\bts\btr работали побайтово и для копирования структур наверняка использовались rep movsw\movsb Цитата ViktorXP @ сам тип ограничен 256 элементами. по этой причине ему не нужно больше 4 байт, для хранения своих значений. 256/8 = 32 байта |
Сообщ.
#11
,
|
|
|
Цитата ViktorXP @ С 3 байтами понятно, я про 7, 11, 15 говорю - там, по идее, тоже должно быть 8, 12, 16 бит.все что выбивается за рамки размера регистров используется через пень колоду. сам подумай сколько тебе нужно лишних манипуляций сделать что бы вычислить бит в третьем байте. если регистра трехбайтового у тебя нет. куда продуктивнее сразу использовать четырехбайтовый геристр Цитата ViktorXP @ Ещё как может. Забей:сам тип никогда не будет занимать больше 4 байт. может иметь размер 1/2/4 var X: set of (a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32); begin ShowMessage(IntToStr(SizeOf(X))) end; Добавлено Цитата leo @ bt/bts/btr/btc (а также bsf/bsr) работают с типом word тоже, с байтами не работают только.тем более, что Intel предупреждает, что битовые операции bt\bts\btr, которые используются в операторах in\include\exclude, работают с 4-байтовыми порциями данных Не знаю, как другие версии (к сожалению, у меня они не пашут), но Delphi7 делает всё через or, and, xor. А если написать X := X + [a14] (для более, чем 32-битного типа), то там вообще ужас-ужас какой-то. Хотя, Include(X, a14) работает нормально. И, может, конечно, в Delphi 20xx/XE/10 тоже нет такого, а все set-типы кратны 4 или 2 байтам. Х/з... |
Сообщ.
#12
,
|
|
|
Цитата leo @ 256/8 = 32 байта хм... плохо у меня с математикой. |
Сообщ.
#13
,
|
|
|
Цитата Jin X @ Не знаю, как другие версии (к сожалению, у меня они не пашут), но Delphi7 делает всё через or, and, xor Нет, логические операции используются только с константами, когда маску для or\and можно определить во время компиляции. А для переменных элементов используются bt\bts\btr. Сравни: var st: set of 0..32; i:integer; begin st:=[]; Include(st,14); //тут OR с маской = 2^14 = $4000 i:=14; Include(st,i); //тут bts ... Цитата Jin X @ И, может, конечно, в Delphi 20xx/XE/10 тоже нет такого, а все set-типы кратны 4 или 2 байтам Нет, все тоже самое, как в D7 |
Сообщ.
#14
,
|
|
|
Цитата leo @ Ага Сравни |