На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> {$A8}
    ExpandedWrap disabled
      {$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.
    В моём понимании (поскольку перед record нет слова packed) результатом должно быть 8, 8... Почему же по факту прога выдаёт 1, 1 ???
    Какой тогда толк от этого ключа ($A) и от слова "packed" ???
      Jin X
      Это обще принятое поведение. Наследует от архитектур где можно было читать только целыми слова кратными 16 бит или 32 бита. Соответственно эта граница и указывалась. В GPP ещё можно запретить переставлять поля.
      В x86 этот ключ используется для правильности работы InterLock - мьютексы, критические секции и так далее. Для них важно чтобы элементы не пересекали границу кэш линии.

      Packed однозначно сжимает.

      А алгоритм выравнивание описан в хэлпе. В двух словах для каждого типа используется своё выравнивание в зависимости от размера. А {A4} указывает максимальное значение как 4.

      ExpandedWrap disabled
          TRec1=
            record
            A: Byte;
            B: DWord;
            end;
         
          TRec2=
            record
            A: DWord;
            B: Byte;
            end;

      Trec1 - будет расжатый, т.е размером 8 байт. А TRec2 5 байт.


      Вирт в своей книги пробовал объяснить сей странный алгоритм, но я так и не понял почему:
      Вирт Н.- Алгоритмы + структуры данных = программы. Мир (1985)
      Сообщение отредактировано: Pavia -
        Pavia, так я о том и говорю, что каждая переменная должна быть выровнена по границе 8 байт (т.к. указано A8). А по факту получается, что всё сжато: каждая байтовая переменная занимает 1 байт.
        Цитата Jin X @
        результатом должно быть 8, 8... Почему же по факту прога выдаёт 1, 1 ?


        Добавлено
        Вот Z4 работает нормально, а вот A4, A8 нет... как-то странно...
          default alignment = sizeOf(type) (simple types)

          AX переопределяет выравнивание для полей sizeOf(field)>=X

          Type alignment masks
            Цитата Jin X @
            так я о том и говорю, что каждая переменная должна быть выровнена по границе 8 байт (т.к. указано A8)

            Нет, ты говоришь о чем-то своем.
            Каждое поле выравнивается на свой собственный размер, если он не превышает значения указанного в опции $А. Т.е. $А не увеличивает границу выравнивания, а наоборот ограничивает ее, делает <= заданного значения. Поэтому $A8 используется по умолчанию и влияет только на выравнивание полей размером более 8 байт, а из простых типов это только extended.
              Всё, парни, спасибо. Перечитал на свежую голову, теперь всё ясно ;)

              p.s. Не совсем в тему, но set of забавный тип. Не занимает никогда 3 байта (т.е. только 1, 2, 4), зато может занимать 5, 6, 7(!) и т.д. прирост идёт по 1 байту (11 в т.ч.)...
              В Delphi7, по крайней мере...
                Цитата Jin X @
                set of забавный тип. Не занимает никогда 3 байта (т.е. только 1, 2, 4), зато может занимать 5, 6, 7(!) и т.д.

                Это связано с тем, что множества размером до integer, могут хранится, передаваться и обрабатываться в регистрах процессора. Соотв-но и их размеры выравниваются на размеры доступных регистров. Если же размер больше integer, то используются операции с памятью с побайтовым доступом, поэтому выравнивание размера не обязательно.
                  Ну тогда, согласись, и для 56 бит (7 байт) было бы проще сделать, например:
                  ExpandedWrap disabled
                    mov eax,[SrcVar]
                    mov [DestVar],eax
                    mov eax,[SrcVar+4]
                    mov [DestVar+4],eax
                  Чем:
                  ExpandedWrap disabled
                    mov eax,[SrcVar]
                    mov [DestVar],eax
                    mov ax,[SrcVar+4]
                    mov [DestVar+4],ax
                    mov al,[SrcVar+6]
                    mov [DestVar+6],al
                    Цитата Jin X @
                    p.s. Не совсем в тему, но set of забавный тип. Не занимает никогда 3 байта (т.е. только 1, 2, 4), зато может занимать 5, 6, 7(!) и т.д. прирост идёт по 1 байту (11 в т.ч.)...

                    сам тип никогда не будет занимать больше 4 байт. может иметь размер 1/2/4
                    (в структуре он может занимать 8 байт, но это обусловлено выравниванием самой структуры, а не типа данных)

                    нюанс связан с самим типом. каждый элемент множества это бит. если у тебя до восьми значений в множестве

                    ExpandedWrap disabled
                      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 байт) было бы проще сделать, например:

                    все что выбивается за рамки размера регистров используется через пень колоду. сам подумай сколько тебе нужно лишних манипуляций сделать что бы вычислить бит в третьем байте. если регистра трехбайтового у тебя нет. куда продуктивнее сразу использовать четырехбайтовый геристр
                      Цитата 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 байта
                        Цитата ViktorXP @
                        все что выбивается за рамки размера регистров используется через пень колоду. сам подумай сколько тебе нужно лишних манипуляций сделать что бы вычислить бит в третьем байте. если регистра трехбайтового у тебя нет. куда продуктивнее сразу использовать четырехбайтовый геристр
                        С 3 байтами понятно, я про 7, 11, 15 говорю - там, по идее, тоже должно быть 8, 12, 16 бит.

                        Цитата ViktorXP @
                        сам тип никогда не будет занимать больше 4 байт. может иметь размер 1/2/4
                        Ещё как может. Забей:
                        ExpandedWrap disabled
                          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 @
                        тем более, что Intel предупреждает, что битовые операции bt\bts\btr, которые используются в операторах in\include\exclude, работают с 4-байтовыми порциями данных
                        bt/bts/btr/btc (а также bsf/bsr) работают с типом word тоже, с байтами не работают только.
                        Не знаю, как другие версии (к сожалению, у меня они не пашут), но Delphi7 делает всё через or, and, xor. А если написать X := X + [a14] (для более, чем 32-битного типа), то там вообще ужас-ужас какой-то. Хотя, Include(X, a14) работает нормально.
                        И, может, конечно, в Delphi 20xx/XE/10 тоже нет такого, а все set-типы кратны 4 или 2 байтам. Х/з...
                          Цитата leo @
                          256/8 = 32 байта

                          хм... плохо у меня с математикой. :D
                            Цитата Jin X @
                            Не знаю, как другие версии (к сожалению, у меня они не пашут), но Delphi7 делает всё через or, and, xor

                            Нет, логические операции используются только с константами, когда маску для or\and можно определить во время компиляции. А для переменных элементов используются bt\bts\btr. Сравни:
                            ExpandedWrap disabled
                              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
                              Цитата leo @
                              Сравни
                              Ага :good:
                              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                              0 пользователей:


                              Рейтинг@Mail.ru
                              [ Script execution time: 0,0414 ]   [ 16 queries used ]   [ Generated: 24.04.24, 18:11 GMT ]