Простая замена вариантного типа в исходных кодах Borland Pascal

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

Эти фокусы известны еще со времен царствования фортрана %D0%A1%D0%BD%D0%B8%D0%BC%D0%BE%D0%BA1

А что помешало именно вышеприведённым образом сделать? Ограничения на использование таких структур? Ломает ли что-нибудь в самом Паскале (или С#, если уж на то пошло) такой концепт? Имеется в виду, есть ли стандартные средства, которые работают грубо некорректно, и молчат об этом?

По поводу небезопасности - смотря где. В том же QVariant или std::variant, boost::variant это все очень неплохо сделано. Но это, конечно, не чистый union. В других языках - честно скажу, не знаю.

Я имею в виду .NET - случайно обратись не к тому полю - и - память испорчена.

Ну, лучшее что я могу придумать это наверное дискорд (Sun Serega#6880). Или вк. Ещё есть скайп, но мне очень не нравится как он работает)). Ну а так - предлагайте.

Хотя, вы ещё можете создать отдельную тему в этом же разделе. Всё же паскаля это касается. Конечно, поведение форума это странное, наверное ему не понравилось что новичок только пришёл и уже много пишет))).

Собственно, @Admin, вы ведь не имеете ничего против создания темы для этого? И, в таком случае стоит повысить @Hssk от базового пользователя до участника. Это лишь стандартная защита форума от неадекватных, так что всё в порядке. А, на сколько я помню, функции базового пользователя не дают загружать файлы и больше 2 картинок в 1 ответе.

Нет проблем - сделал

2 лайка

А по моему ничего не поменялось)):

И.е. использовать в вышеприведенном концепте что-то вроде

union IP 
{
    uint32_t complete;
    struct 
    {
        uint8_t b1;
        ..
    } bt;
};

нельзя? Записали в первое поле - читаем только из него?

Да. Сделал Hssk участником

Непроизносимый ник почему-то навеял в памяти старый политический анекдот:

КПСС - набор глухих согласных

.

А КПРФ? :smile:

Странно, а я почему то сразу легко прочитал это как хаск))

Ну не знаю…дрк - это “дырка” или “дурак” ?

P.S. А на самом деле - “доярка” )))

@Hssk Если с атрибутами .NET в этом Паскале у вас не получится то что надо, тогда попробуйте заморскую учебную среду от (внимание!) тунисского сообщества учителей информатики :footprints: :sunglasses: Pascal XE – она, конечно, простенькая (без дебаггера), местами кривая, глючная и недопиленная (напр., с поддержкой русских и прочих нелатинских кодировок в исходниках там беда), со своим довольно своеобразным GUI :see_no_evil:, но легкая и вполне работоспособная для простых задач и экспериментов.

Поддерживает “из коробки” сразу 3 компилятора для Win32 – Virtual Pascal 2.1, Free Pascal 3.0.4 и GNU Pascal (2007-09-04) – можно переключаться между ними на лету. Рекомендуется всегда подключать модуль Crt или WinCrt для более удобной отладки (вывод дебаг-информации о номере строки с ошибкой и ожидание нажатия AnyKey в консоли).

Все три компилятора поддерживают нужные вам записи с вариантами (+ дополнительные директивы по выравниванию полей и кода), а также упакованные записи и массивы. В вашем случае (для FPC или GPC) для бинарной совместимости записей со старым 16-битным BP-кодом потребуется использование в начале программ директивы {$PackRecords 1} или, как вариант, {$PackRecords 2}. В комплекте идет встроенная базовая справка из Borland TPW 1.5.

Думаю, это будет самой простой для вас способ подобрать себе подходящий компилятор для старых исходников.

P.S. По умолчанию там язык, кажется, французский, но легко переключается на английский или арабский :slight_smile: .

То есть, извечная проблема type-cast vs type-transfer vs free-union vs absolute vs pointer vs MEM vs asm трактовки одной области данных под разные типы?

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

Type 
 Variant_A = record
  ID: byte; //сигнатура 1
  поле1: тип1;
  поле2: тип2;
//бла-бла-бла
end;

 Variant_B = record
  ID: byte; //сигнатура 2
  поле1: тип3;
  поле2: тип4;
 . . .
  поле5: тип2
//бла-бла-бла
end;

Var
 _A: ^Variant_A; //указатель на тип А
 _B: ^Variant_B; // и тип Б
. . .
//буфер по максимально возможному размеру обеих записей
BUFF: array[1..max_size_of_records] of byte;
. . .
F: file; //нетипизированный файл
_count: word; //вспомогательный счётчик
. . .
BEGIN
//вместо {$i-} и ручного контроля лучше через исключения 
  Assign(F, 'EOB1.map');
  Reset(F, SizeOf(BUFF));
  
  _A := @BUFF; //ссылка на буфер в варианте А
  _B := @BUFF; //и вариант Б

  BlockRead(F, BUFF, Sizeof(BUFF), _count); //чтение в буфер
 
 While _count > 0 Do //пока есть что читать из файла
begin
 //Лучше через CASE, хотя можно и if BUFF[1]=1 then abc:=_A^.поле2 else bcd:=_B^.поле5 и т.д.
 //не забывайте контролировать ID ибо epic_fail
 . . .   
BlockRead(F, BUFF, Sizeof(BUFFER), _count);
  end;//while

Код не проверял, но суть, думаю, понятна.

Это не сработает:

  _A := @BUFF; //ссылка на буфер в варианте А
  _B := @BUFF; //и вариант Б

И откуда взялась процедура BlockRead?

Вестимо, из Дельфей. Я уж давно талдычу, что эти Дельфи-совместимости только на дно тянут, как якорь, а зачем они - непонятно. На Делфи в основном писали те, кому был важен визуальный интерфейс или связи с СУБД, а тут этих этих вещичек нет, так что переход сюда с Делфи маловероятен и ни к чему тащить за собой весь тот багаж. Наверно, так на 15-20% в языке бы поубавилось разных примочек ради совместимости.

2 лайка

Если бы только примочки… С дельфи идёт непостоянность компилятора, к примеру:

type
  t1=class
    a:byte
  end;//ok
  
  t2=class
    function a:byte
  end;//Ошибка: ожидалось ';'

begin end.

А почему же тогда Вы против добавления фичей из C#?