Конференция "Начинающим" » Выравнивание (размер) параметров Enum&Set при передаче/получении
 
  • Чародей Ученика (08.07.18 01:58) [0]
    Доброй ночи! Подскажите пожалуйста...
    Я объявил перечисление и множество:
    type
     EMyEnum = (
       MyEnumA,
       MyEnumB,
       MyEnumC
     );
     TMyEnum = EMyEnum;
     TMySet = Set Of TMyEnum;

    И написал функцию:
    procedure MyTest(F: DWORD; E: TMyEnum; M: DWORD; S: TMySet; L: DWORD);
    begin
    // SizeOf(E) == 1
    // SizeOf(S) == 1
    ...
    end;

    Переменные-параметры получаются размером один байт. А сколько будет "выделено места" при их передаче? Тоже один? Или четыре? Этим можно как-то управлять? Я хочу чтоб все параметры были одинакового размера, чтоб в другой программе можно было импортировать и использовать мою функцию как: MyTest(DWORD, DWORD, DWORD, DWORD, DWORD).
    В данном случае мне даже не важно сколько будет SizeOf самой переменной, меня пока интересует конкретно выравнивание при передаче параметров. Хотя и про размер переменных тоже было бы хорошо разобраться, на будущее.
    Спасибо!
  • Игорь Шевченко © (08.07.18 10:46) [1]
    use Ord
  • Игорь Шевченко © (08.07.18 10:49) [2]
  • Чародей Ученика (08.07.18 12:45) [3]
    Ord это в смысле функция возвращающая Integer или Int64? А зачем она мне тут?
    Я хочу чтоб унифицированный заголовок моей функции был "пять параметров по 4 байта каждый", для совместимости, но при этом в Делфи использовать некоторые параметры как перечисление или множество, для удобства и исключения ошибок.

    >> but a set always resides in memory if it is larger than the platform-dependent integer type

    Мне не нужно "больше чем integer type", мне нужно "точно равно 4 байта" или же "точно равно размеру integer type".

    Кажется нашёл такое:
    type
     {$MINENUMSIZE 4}
     EMyEnum = (
       MyEnumA,
       MyEnumB,
       MyEnumC
     );
     TMyEnum = EMyEnum;
     TMySet = Set Of TMyEnum;
     {$MINENUMSIZE 1}

    Но поправилось только первое, а второе всё равно один байт:
    procedure MyTest(F: DWORD; E: TMyEnum; M: DWORD; S: TMySet; L: DWORD);
    begin
    // SizeOf(E) == 4
    // SizeOf(S) == 1
    ...
    end;
  • Чародей Ученика (08.07.18 13:38) [4]
    Надо чтоб параметры M и L были строго по смещению 8 и 16. Может просто добавить какой-нибудь stdcall? Чтоб функцию можно было импортировать как
    void MyTest(DWORD F, DWORD E, DWORD M, DWORD S, DWORD L);


    Научите пожалуйста, как смотреть/понимать в отладчике код вызова этой функции - сколько передаётся параметров, как передаётся, и какого они размера?
  • Pavia © (08.07.18 16:31) [5]
    Игорь уже дал описание.
    Разве что дополню:
    http://dwarfstd.org/doc/Dwarf3.pdf
  • Pavia © (08.07.18 16:53) [6]

    > Научите пожалуйста, как смотреть/понимать в отладчике код
    > вызова этой функции - сколько передаётся параметров, как
    > передаётся, и какого они размера?

    http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Program_Control_(Delphi)#Register_Convention
  • Чародей Ученика (09.07.18 00:06) [7]
    Описание чего? Там просто "что такое Set", я и так знаю что это. Но я же не это спрашиваю - а как заставить его быть размером в 4 байта. Этого там нету.

    Что за Юникс-Гномы я не понял совсем...

    По последней ссылке написано:

    >> Sets, records, and static arrays of 1, 2, or 4 bytes are passed as 8-bit, 16-bit, and 32bit values.

    Вывод - передаётся не так как я хочу. Ну а как принудительно заставить всегда быть 32bit? Там не сказано. Никак?
  • icp © (09.07.18 08:28) [8]
    сет это 256 возможных членов.
    то есть физически это максимум 256 бит или 32 байта.

    а как заставить его быть размером в 4 байта

    чтобы стало 4 байта, надо сделать твой енум нужной длины (32 члена) и включить максимальный член в множество.

    либо при проектировании выбирать типы данных не от балды, а со смыслом.
  • KSergey © (09.07.18 08:54) [9]
    Если нужна связь с программами на других языках - я бы не рисковал
    Просто объявил ручками константы нужные (в каждой один бит в 1) и сам тип объявил нужным мне

    Ибо гадать с размерами и проч., а потом вылавливать не понятные кривости поведения - удовольствие так себе.
  • Pavia © (09.07.18 09:30) [10]

    >  Там не сказано. Никак?

    Зачем это вам? Всё равно в других языках нет аналога set of. Так что работать с ним не сможете. Делать конвертер, так лучше сразу со стороны вашей библиотеки. Тем более это внешняя связь, а значит данные требуют проверки и нормировки пред их применением.
  • sniknik © (09.07.18 11:22) [11]
    если нужны DWORD значит и переменные должны быть DWORD, в масиве/еще как то не принципиально (если в общем а не под задачу).

    > Чтоб функцию можно было импортировать как void MyTest(DWORD F, DWORD E, DWORD M, DWORD S, DWORD L);
    и кстати параметры в функцию передаются через стек, а не массивом/сетом за раз... если понял смысл поста.
  • Чародей Ученика (09.07.18 14:29) [12]
    Я хочу использовать в своём коде удобные мне вещи - перечисление и множество.
    Читать удобнее, писать удобнее (Code Completion адаптируются), дорабатывать удобнее, RTTI подхватывает тип, отлаживать удобнее. Плюс они добавляют дополнительную защиту от неправильного использования.
    А когда какую-то часть функций понадобится экспортировать - то эти "другие языки которые не уметь set of" - пусть себе тогда они объявляют заголовок как DWORD и передают константы (раз уж они не могут иначе).
    Чего это я должен отказываться от очень хороших плюшек, из-за того что другие чего-то там не умеют?

    > чтобы стало 4 байта, надо сделать твой енум нужной длины (32 члена) и включить максимальный член в множество.

    гм! Добавил пунктов MyEnum* до 32 штук - стало 4 байта! Спасибо!
    Вот только что делать если мне их там стока не нужно? Допустим что нужно три... Мешаются же остальные. Можно ли их как-то оставить в объявлении, но исключить из использования?
    Имею ввиду запретить использовать в коде и не показывать в Code Completion? Deprecated получается применять только ко всему перечислению...

    type
     {$MINENUMSIZE 4}
     EMyEnum = (
       MyEnumA, // 1
       MyEnumB, // 2
       MyEnumC, // 3
       MyEnumReserved4,
       MyEnumReserved5,
       MyEnumReserved6,
       MyEnumReserved7,
       MyEnumReserved8,
       MyEnumReserved9,
       MyEnumReserved10,
       MyEnumReserved11,
       MyEnumReserved12,
       MyEnumReserved13,
       MyEnumReserved14,
       MyEnumReserved15,
       MyEnumReserved16,
       MyEnumReserved17,
       MyEnumReserved18,
       MyEnumReserved19,
       MyEnumReserved20,
       MyEnumReserved21,
       MyEnumReserved22,
       MyEnumReserved23,
       MyEnumReserved24,
       MyEnumReserved25,
       MyEnumReserved26,
       MyEnumReserved27,
       MyEnumReserved28,
       MyEnumReserved29,
       MyEnumReserved30,
       MyEnumReserved31,
       MyEnumReserved32
     );
     {$MINENUMSIZE 1}
  • sniknik © (09.07.18 15:10) [13]
    > Допустим что нужно три...
    4 байта это всего один DWORD, три байта никак нельзя, если конечно хочешь "делить память" DWORD-ами.
    так то у set-а увеличение побайтное, вроде... (не проверял, может еще как то выравнивание влияет), т.е. убери последние минимум 8 максимум 15 значений и будет тебе 3 байта.
  • KSergey © (09.07.18 15:31) [14]
    > Чародей Ученика   (09.07.18 14:29) [12]
    > А когда какую-то часть функций понадобится экспортировать
    > - то эти "другие языки которые не уметь set of" - пусть
    > себе тогда они объявляют заголовок как DWORD и передают
    > константы (раз уж они не могут иначе).

    Другие просто скажут "а иди ты лесом с таким интерфейсом"
    И будут правы.

    "Если ты плюнешь в коллектив - коллектив утрётся. Если коллектив плюнет в тебя - утонешь."
  • Чародей Ученика (09.07.18 16:41) [15]
    > три байта никак нельзя

    Это было не про "байты", а про количество элементов в описании EMyEnum.
    А размер нужен эквивалентный DWORD. Но он уже получен. Просто неудобно что 29ть лишних холостых MyEnum* болтаются.

    > Другие просто скажут "а иди ты лесом с таким интерфейсом"

    А какое дело "другим" до внутреннего устройства моей системы? И почему я должен из-за кого-то урезать свой внутренний инструментарий?
    И я же как раз универсальности и добиваюсь: умеете работать с "set of" - используйте вот такой-то "set of", не умеете - используйте DWORD и такие-то константы. Всё по желанию/возможностям.
  • sniknik © (09.07.18 17:30) [16]
    > Просто неудобно что 29ть лишних холостых MyEnum* болтаются.
    set of byte - максимальный размер.

    TMyEnumWord = 0..31;
    TMySet = set of TMyEnumWord; - "удобный" размер;
  • sniknik © (09.07.18 17:36) [17]
    > не умеете - используйте DWORD и такие-то константы.
    с константами геморрой будет, типа в сете 1, а в дворде 4096 и т.д. ... ну или типа, смотря как там в памяти хранится, а оно вовсе не биты в линеечку слева направо как тебе похоже представляется.
  • sniknik © (09.07.18 17:45) [18]
    > смотря как там в памяти хранится
    хотя, с первой половиной (до 16) проблем не будет, после значение скачет, т.к. старший ворд располагается по младшему адресу... проверь
    var
     s: set of 0..31;
     d: dword absolute s;
    begin
     s:= [16]; //17
     Edit1.Text:= IntToStr(d);
    end;

  • Прохосый (09.07.18 17:57) [19]
 
Конференция "Начинающим" » Выравнивание (размер) параметров Enum&Set при передаче/получении
Есть новые Нет новых   [134427   +34][b:0][p:0.002]