На главную Наши проекты:
Журнал   ·   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_
  
> Основные типы данных , overload-функция
    Хочу перечислить все основные типы данных, чтобы перегрузить (overload) функцию всеми ими.
    Из целых выбрал Byte, Integer и Int64, потому как на Word при задании числа, скажем, "10" компилер ругается, мол "Ambiguous overload call".
    Но это не страшно. А страшно то, что он ругается на AnsiChar vs PAnsiChar. Как тут быть?
    Вообще, как определить все типы, которые никогда не будут вызывать подобной ошибки?
    С Single, Double, Extended история такая: при использовании числа вроде 1.0 используется Extended, даже если результат присваивается Single, ну да ладно.

    p.s. К основным причислил ещё, разумеется, Boolean, Pointer, Variant, TObject, а также TClass, IInterface, TGUID, TPoint, TRect.
    Что ещё стоит взять? :)

    p.p.s. С var-параметрами проблем нет. Вернее, хорошо бы объединить, скажем, Byte и Shortint, но это нестрашно.
      Jin X
      Берём по порядку варинт из System.pas

      Скрытый текст

      varEmpty = $0000; { vt_empty 0 }
      varNull = $0001; { vt_null 1 }
      varSmallint = $0002; { vt_i2 2 }
      varInteger = $0003; { vt_i4 3 }
      varSingle = $0004; { vt_r4 4 }
      varDouble = $0005; { vt_r8 5 }
      varCurrency = $0006; { vt_cy 6 }
      varDate = $0007; { vt_date 7 }
      varOleStr = $0008; { vt_bstr 8 }
      varDispatch = $0009; { vt_dispatch 9 }
      varError = $000A; { vt_error 10 }
      varBoolean = $000B; { vt_bool 11 }
      varVariant = $000C; { vt_variant 12 }
      varUnknown = $000D; { vt_unknown 13 }
      //varDecimal = $000E; { vt_decimal 14 } {UNSUPPORTED as of v6.x code base}
      //varUndef0F = $000F; { undefined 15 } {UNSUPPORTED per Microsoft}
      varShortInt = $0010; { vt_i1 16 }
      varByte = $0011; { vt_ui1 17 }
      varWord = $0012; { vt_ui2 18 }
      varLongWord = $0013; { vt_ui4 19 }
      varInt64 = $0014; { vt_i8 20 }
      //varWord64 = $0015; { vt_ui8 21 } {UNSUPPORTED as of v6.x code base}
      { if adding new items, update Variants' varLast, BaseTypeMap and OpTypeMap }

      varStrArg = $0048; { vt_clsid 72 }
      varString = $0100; { Pascal string 256 } {not OLE compatible }
      varAny = $0101; { Corba any 257 } {not OLE compatible }
      // custom types range from $110 (272) to $7FF (2047)

      varTypeMask = $0FFF;
      varArray = $2000;
      varByRef = $4000;

      { TVarRec.VType values }

      vtInteger = 0;
      vtBoolean = 1;
      vtChar = 2;
      vtExtended = 3;
      vtString = 4;
      vtPointer = 5;
      vtPChar = 6;
      vtObject = 7;
      vtClass = 8;
      vtWideChar = 9;
      vtPWideChar = 10;
      vtAnsiString = 11;
      vtCurrency = 12;
      vtVariant = 13;
      vtInterface = 14;
      vtWideString = 15;
      vtInt64 = 16;

      { Virtual method table entries }

      vmtSelfPtr = -76;
      vmtIntfTable = -72;
      vmtAutoTable = -68;
      vmtInitTable = -64;
      vmtTypeInfo = -60;
      vmtFieldTable = -56;
      vmtMethodTable = -52;
      vmtDynamicTable = -48;
      vmtClassName = -44;
      vmtInstanceSize = -40;
      vmtParent = -36;
      vmtSafeCallException = -32 deprecated; // don't use these constants.
      vmtAfterConstruction = -28 deprecated; // use VMTOFFSET in asm code instead
      vmtBeforeDestruction = -24 deprecated;
      vmtDispatch = -20 deprecated;
      vmtDefaultHandler = -16 deprecated;
      vmtNewInstance = -12 deprecated;
      vmtFreeInstance = -8 deprecated;
      vmtDestroy = -4 deprecated;

      vmtQueryInterface = 0 deprecated;
      vmtAddRef = 4 deprecated;
      vmtRelease = 8 deprecated;
      vmtCreateObject = 12 deprecated;


      Пустого типа в паскале нет. Но есть пустой рекорд.
      Ещё указатель на пустой рекорд.
      PVoidRecord=^TVoidRecord;
      TVoidRecord=record
      end;

      Вместо Word64 есть тип Uint64

      String - тут их три типа ShortString, WideString,

      Скрытый текст
      PShortString = ^ShortString;
      PAnsiString = ^AnsiString;
      PWideString = ^WideString;
      PString = PAnsiString;

      UCS2Char = WideChar;
      PUCS2Char = PWideChar;
      UCS4Char = type LongWord;
      {$NODEFINE UCS4CHAR}
      PUCS4Char = ^UCS4Char;
      {$NODEFINE PUCS4CHAR}
      TUCS4CharArray = array [0..$effffff] of UCS4Char;
      PUCS4CharArray = ^TUCS4CharArray;
      UCS4String = array of UCS4Char;
      {$NODEFINE UCS4String}

      UTF8String = type string;
      PUTF8String = ^UTF8String;
      {$NODEFINE UTF8String}
      {$NODEFINE PUTF8String}

      IntegerArray = array[0..$effffff] of Integer;
      PIntegerArray = ^IntegerArray;
      PointerArray = array [0..512*1024*1024 - 2] of Pointer;
      PPointerArray = ^PointerArray;
      TBoundArray = array of Integer;
      TPCharArray = packed array[0..(MaxLongint div SizeOf(PChar))-1] of PChar;
      PPCharArray = ^TPCharArray;

      (*$HPPEMIT 'namespace System' *)
      (*$HPPEMIT '{' *)
      (*$HPPEMIT ' typedef int *PLongint;' *)
      (*$HPPEMIT '}' *)
      PLongint = ^Longint;
      {$EXTERNALSYM PLongint}
      PInteger = ^Integer;
      PCardinal = ^Cardinal;
      PWord = ^Word;
      PSmallInt = ^SmallInt;
      PByte = ^Byte;
      PShortInt = ^ShortInt;
      PInt64 = ^Int64;
      PLongWord = ^LongWord;
      PSingle = ^Single;
      PDouble = ^Double;
      PDate = ^Double;
      PDispatch = ^IDispatch;
      PPDispatch = ^PDispatch;
      PError = ^LongWord;
      PWordBool = ^WordBool;
      PUnknown = ^IUnknown;
      PPUnknown = ^PUnknown;
      {$NODEFINE PByte}
      PPWideChar = ^PWideChar;
      PPChar = ^PChar;
      PPAnsiChar = PPChar;
      PExtended = ^Extended;
      PComp = ^Comp;
      PCurrency = ^Currency;
      PVariant = ^Variant;
      POleVariant = ^OleVariant;
      PPointer = ^Pointer;
      PBoolean = ^Boolean;

      TDateTime = type Double;
      PDateTime = ^TDateTime;

      THandle = LongWord;


      Добавлено
      Jin X
      Еще в догонку. С функциями интересно. Если результатом будет тип рекорд, то он передаётся в функцию последним параметром как Var.
      И строки тоже интересным способом обрабатываюся. (Не считая авто преобразования PChar для функций)
        Разные Pointer-типы делать смысла нет, ибо обычного Pointer'а достаточно, а его можно привести к нужному (на все типы не наделаешь). А также всякие WordBool'ы, THandle, TDateTime, OleVariant, пустую запись и пр. тоже в топку :)
        Я имел в виду, по большому счёту, какие типы чаще всего используются? Вот я взял TGUID, TPoint, TRect. Больше ничего пока в голову не приходит. Ну разве что TMsg, TMessage и TRTLCriticalSection, но это, в общем-то, можно и через указатели передать (собственно, как и TGUID, TPoint, TRect) :)

        А ещё больше волнует первый вопрос: как подружить PChar и Char? Хотя, как оказалось, эта проблема актуальна до D7, дальше проблема решается автоматом :) А для D7 придётся менять название для Char'а персонально...
          OMG, теперь надо подружить Integer и Cardinal. Если -1 или 3 млрд, то понятно какой тип, а все промежуточные выдают error в D7... :wall:
            Цитата Jin X @
            Я имел в виду, по большому счёту, какие типы чаще всего используются?

            Это не проблема частоту могу посчитать. Только скажите по каким файлам.
              Цитата Jin X @
              надо подружить Integer и Cardinal. Если -1 или 3 млрд, то понятно какой тип, а все промежуточные выдают error в D7..

              Разумеется, что при передаче в overload-функции константы, которая подходит по различные overload-варианты, компилер не знает, что делать и выдает ошибку. Выход - либо использовать не константы, а переменные соответствующего типа, либо при передаче константы явно указывать ее тип, например, integer(1), cardinal(1), single(1) и т.п.
              Сообщение отредактировано: leo -
                Цитата Jin X @
                как подружить PChar и Char? ... А для D7 придётся менять название для Char'а персонально...

                Для Char и PChar ситуация хитрее, т.к. это совместимые типы, поэтому простое указание типа константы, например Char('A') тут ничего не дает. Но можно использовать некую фишку (функцию или приведение типа), которая однозначно выдает один символ Char, например String('A')[1].

                PS: Интересные баги D7. Приведение типа Chr(Ord('v')) в D7 не катит - выдает ошибку неоднозначности.
                Еще более интересный баг: приведение одного символа к pChar('A') на самом деле выдает не указатель на символ, а его значение (код символа), поэтому приведения типов pChar('A') и pChar('A')^ оба приводят к эксепшену при вызове overloаd-функций (в первом случае код символа передается в функцию, ожидающую pChar, а во втором делается попытка чтения первого символа по неверному указателю для передачи в функцию ожидающую Char). Если же использовать не один символ, а пару или более, то все работает нормально, например pChar('AA')^ выдает код первого символа и вызывает функцию, ожидающую Char (но в этом случае и более короткий вариант 'AA'[1] тоже работает).
                  Pavia, да не надо считать, спасибо :)
                  leo, это всё неудобно.

                  Вообще, в 2005 очень много нововведений сделано (inline, for in, инициализация динамических массивов, статические классовые методы, классовые свойства, ненаследуемые классы (sealed), абстрактные классы, strict, final). Тем не менее, D7 вроде как более популярен почему-то.
                  В 2006 поменьше, но тоже неплохие: методы записей, перегрузка операторов, классовые переменные, FastMM(!).
                  В 2007 ничего нового.
                  В 2009: дженерики (типа), анонимные методы, Exit(Result), UNICODE и пр. по мелочи.
                  В 2010: конструкторы и деструкторы классов (хорошая тема!) и пр.
                  А дальше уже так себе нововведения (не считая поддержки x64, ну хелперов, может):
                  XE: RegExp и пр.
                  XE2: x64 и пр.
                  XE3: хелперы записей, атомарные интринсики и пр.
                  XE4: volatile, weak, ref и пр.
                  XE7: TParallel, новые операции с дин.массивами и пр.

                  Я вот никак не могу понять: ПОЧЕМУ В DELPHI НЕ СДЕЛАЮТ интринсики (ассемблер в inline - нафига его запретили?!!!) и дефайны (inline-функции всё-таки не совсем то)? :wall:
                  Ну про ++ и ?: я уж молчу...

                  p.s. А вообще, хорошо было бы ещё иметь возможность передавать _небольшие_функциональные_блоки_ в качестве параметров. Только не так громоздко, как анонимные методы (как с точки зрения оформления, так и сточки зрения внутреннего устройства). А, скажем, вот так:
                  ExpandedWrap disabled
                    function X(func Z: Integer): Integer;
                    begin
                      Result := 2*Z;
                    end;
                    . . .
                    X([GetData(0)]);
                  Т.е. чтобы функция Z не вычислялась до тех пор, пока мы её не запустим.

                  p.p.s. "Оптимизация" Delphi убивает, конечно. Знаете как Delphi проводит вот такую операцию?
                  ExpandedWrap disabled
                    {$O+}
                     
                    function X(A: Int64): Int64;
                    begin
                      Result := A;
                    end;
                     
                    function Y(A: Int64): Int64;
                    begin
                      Result := X(A)+1;
                    end;
                     
                    begin
                      asm int 3 end;
                      Y(1)
                    end.
                  Это X:
                  user posted image
                  А это Y:
                  user posted image
                  И вы думаете, так делает только D7? Нет, друзья, Tokyo тупит точно так же! Это ппц :facepalm:
                    Цитата Jin X @
                    Это ппц

                    А как правильно? :)
                      Цитата Shaggy @
                      А как правильно?
                      В X достаточно 2-х push'ей, call'а и add+adc (ну и ret, разумеется). Хотя, даже при таком раскладе мне непонятно, почему Int64 передаётся не в паре edx:eax, а в стеке.
                      А в Y - mov eax,[ebp-8] и mov edx,[ebp-4] (которые перед push'ами). Всё остальное - холостой код (выделение и освобождение места под локальные переменные, запись в эти локальные переменные из регистров и тут же чтение обратно в регистры).

                      Добавлено
                      А вообще, по логике (учитывая, что используется соглашение о вызове register)

                      Исходный:
                      ExpandedWrap disabled
                        mov eax,1
                        cdq
                        call Y

                      Y:
                      ExpandedWrap disabled
                        call X
                        add eax,1
                        adc edx,0
                        ret

                      X:
                      ExpandedWrap disabled
                        ret
                        Цитата leo @
                        Приведение типа Chr(Ord('v')) в D7 не катит - выдает ошибку неоднозначности.
                        В каком смысле? Всё нормально работает.
                          Цитата Jin X @
                          это всё неудобно.

                          И что? Для числовых констант явное указание типа при вызове overload - это единственный способ разрешения неоднозначности, т.к. в перекрывающемся диапазоне значений разных типов компилятор понятия не имеет какую из overload-функцию вызвать, и правильно делает, что выдает ошибку. А вот с Char\pChar - действительно косяк (по крайней мере в D7).

                          Цитата Jin X @
                          В каком смысле? Всё нормально работает.

                          У меня не работает. В том смысле, что передача Chr(Ord('v')) в оверлоад-функцию с типами параметров Char и pChar выдает ошибку неоднозначности.
                            Цитата leo @
                            У меня не работает. В том смысле, что передача Chr(Ord('v')) в оверлоад-функцию с типами параметров Char и pChar выдает ошибку неоднозначности.
                            Ясно, я подумал, что речь не про overload, поэтому и удивился.

                            Добавлено
                            Цитата leo @
                            И что? Для числовых констант явное указание типа при вызове overload - это единственный способ разрешения неоднозначности, т.к. в перекрывающемся диапазоне значений разных типов компилятор понятия не имеет какую из overload-функцию вызвать, и правильно делает, что выдает ошибку.
                            2005+ не выдаёт...
                              По числам - параметры все равно передаются через целый регистр, т.ч. достаточно такого:
                              ExpandedWrap disabled
                                ifdef x32
                                  Func(Integer)
                                  Func(Cardinal)
                                endif
                                  Func(Int64)
                                  Func(UInt64)


                              Цитата Jin X @
                              ассемблер в inline - нафига его запретили?

                              Имхо, потому что в этом случае невозможно гарантировать состояние регистров.

                              Цитата Jin X @
                              дефайны

                              Фича крайне спорная. При наличии inline случаи полезного применения оной очень редки. Паскаль не Си, чтобы давать возможность превратить код в рататуй.

                              Цитата Jin X @
                              Ну про ++ и ?: я уж молчу...

                              Первое также нужно весьма редко при отсутствии сишных конструкций циклов, а вот второе да, было бы полезно... но опять же, философия языка - простота и естественность в ущерб краткости.

                              Цитата Jin X @
                              Я вот никак не могу понять: ПОЧЕМУ В DELPHI НЕ СДЕЛАЮТ

                              Учитывая чехарду с владельцами, удивительно, что хоть что-то делают

                              Цитата Jin X @
                              p.p.s. "Оптимизация" Delphi убивает, конечно. Знаете как Delphi проводит вот такую операцию?

                              А каков плюс в оптимизированном варианте, помимо красивости кода? Бенчмарки запускал?
                                Цитата Fr0sT @
                                Имхо, потому что в этом случае невозможно гарантировать состояние регистров.
                                А если делать call/ret, то гарантировать можно?
                                Всё так же: меняются eax/rax, ecx/rcx, edx/rdx, r8-r11, остальные сохраняются... в чём проблема? В Си же вроде проблем с этим нет...

                                Цитата Fr0sT @
                                Бенчмарки запускал?
                                А какой смысл их запускать, если там просто лишние куски кода? :)
                                Т.е. убираем кусок, всё работает так же. По любому медленнее от этого не станет!
                                  Цитата Jin X @
                                  А какой смысл их запускать, если там просто лишние куски кода?

                                  Если разница составляет миллисекунды на миллиарды итераций, то смысла вычищать эти лишние куски просто нет
                                    Я говорю о проблемах оптимизации в Delphi (в целом). Когда ты пишешь модуль не для конкретного случая, а для любых проектов, которые будешь писать в будущей (и не только ты, может быть), то думать об оптимизации надо (не всегда фанатично - тут спору нет).
                                    Программы пишутся разные и для разных целей, так что где-то это незаметные микро- и наносекунды, а где-то они превращаются в десятки секунд, минуты и часы. Представь себе, например, три архиватора. В одном отключена опция оптимизации, в другом включена, но корявая, а в третьем – максимально качественная. Я думаю, что при всех прочих равных, разница будет заметна и предпочтение ты отдашь третьему...
                                      Ну, проблемы в оптимизации компилятора на порядок выше, чем пара лишних асмовых инструкций. Начать хотя бы с того, что весь код под x64, не говоря о других платформах, написан на чистом паскале. Причем до недавнего времени - написан криво, с ужасным падением перформанса. Так что если уж выжимать тут все до наносекунды, то юзать чистый асм и самый простой набор возможностей языка. Потому как ты можешь наваять мега-быструю конверсию strtoint, но вызов ее через RTTI сразу похоронит все ухищрения.

                                      Добавлено
                                      Цитата Jin X @
                                      Я думаю, что при всех прочих равных, разница будет заметна и предпочтение ты отдашь третьему...

                                      Если разница будет в пару секунд на 100 мб, то не буду заморачиваться). Тем более что мега-оптимизированный код в плане поддержки просто ничто по сравнению с не очень оптимальным, но качественным и понятным.
                                      К тому же проблема переносимости.
                                      Сообщение отредактировано: Fr0sT -
                                        Цитата Fr0sT @
                                        Тем более что мега-оптимизированный код в плане поддержки просто ничто по сравнению с не очень оптимальным, но качественным и понятным.
                                        Так, я ж говорю про оптимизацию компилера Delphi. А не про ручную.
                                        Да, к сожалению, сжатие аудио/видео писать на "чистом паскале" – далеко не самый оптимальный вариант...
                                        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                        0 пользователей:


                                        Рейтинг@Mail.ru
                                        [ Script execution time: 0,0662 ]   [ 17 queries used ]   [ Generated: 19.04.24, 03:40 GMT ]