Delphi, Asm, C, WinAPI, PHP, ..., FAQ |
Добро пожаловать, гость ( Вход | Регистрация )
Delphi, Asm, C, WinAPI, PHP, ..., FAQ |
-=CHE@TER=- |
Oct 27 2016, 15:59
Сообщение
#141
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Отличный пример наглядно иллюстрирующий почему если ты не чистишь память сразу после выделения (или не выделяешь с флагом автоматической очистки типа HEAP_ZERO_MEMORY / LMEM_ZEROINIT / GMEM_ZEROINIT и т.п.), то ты - баобаб.
|
-=CHE@TER=- |
Nov 23 2016, 15:03
Сообщение
#142
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Натолкнулся на то, что в нескольких играх используется LZSS, описанный в моём сообщении выше. Нашёл ещё одну вариацию - применялась в старых играх от Blizzard:Но, есть одно отличие MS-LZSS (Microsoft LZSS) от классического LZSS (который, похоже, используется во многих играх), без которого на выходе получится не файл, а что попало. - Warcraft: Orcs and Humans - Blackthorne - Lost Vikings В ближайшее время распаковщик на сайт добавлю (там нет имён и через флаги у размера / смещения файла определяется сжат он или нет). Кому интересно, описываю изменения в том алгоритме что я приводил ранее. Вот эти строки: CODE FillChar(buff[0], $FFF + 1, 32); I:=($FFF + 1) - 16; ... J:=J + ((Len And $F0) ShL 4); Len:=(Len And $0F) + 3; Заменяются этими: CODE FillChar(buff[0], $FFF + 1, 0); I:=0; ... J:=J + ((Len And $0F) ShL 8); Len:=((Len And $F0) ShR 4) + 3; И всё. Спасибо сказали:
|
-=CHE@TER=- |
Jan 29 2017, 19:55
Сообщение
#143
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
AsmBB
Форум написанный на FASM. Нет, вы не ослышались. Да, это Assembler. Дизайн дикий, функционал скромный, но идея интересная - наверняка потом в какой-нибудь KolibriOS интегрируют. (*улыбается*) |
Siberian GRemlin |
Feb 27 2017, 09:33
Сообщение
#144
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Установил игру на 64-разрядную систему. Программа устанавливается через 32-разрядную InstallShield 11.0, но каким-то образом пишет данные в область реестра доступную только 64-разрядным приложениям. Например, создаёт ветку, которая в 64-разрядном редакторе реестра доступна, а в 32-разрядном отсутствует.
CODE HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-21-3391727471-1739702130-609907194-1000\Components\66EEC61806F24F94D949A665B121C141 Таким образом, я из своего 32-разрядного приложения не могу получить путь к установленной игре, так как это единственное место в системе, где он указывается. Игра, кстати, 2006 года и 32-разрядная. Кто-нибудь сталкивался с такой проблемой? Предполагаю, что решение существует, но не могу корректно сформулировать поисковый запрос. Добавлено. Нашёл кривое решение через экспорт ветки в файл, который нужно затем читать. CODE REG.EXE export HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-21-3391727471-1739702130-609907194-1000\Components\66EEC61806F24F94D949A665B121C141 test.reg Добавлено позже. Похоже, из 32-разрядного приложения вызывается только 32-разрядная версия REG.EXE со всеми вытекающими. Идиотство. |
-=CHE@TER=- |
Feb 28 2017, 08:16
Сообщение
#145
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Переместил твоё сообщение в более подходящую тему.
Как я понял, тебе поможет KEY_WOW64_64KEY при вызове RegOpenKeyEx(). Обрати внимание, что эта штука не будет работать под Windows 2000. Ещё снизу см. Note - есть другой способ без флагов, но "it's stable but it should be considered an implementation detail subject to change". Такие дела. |
-=CHE@TER=- |
Jul 2 2017, 14:16
Сообщение
#146
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Может кому пригодится: libunpak.zip (~16 Kb)
Библиотека для Delphi 7, где я собрал бинарники для последних: - puff() из zlib (распаковывает deflate) - blast() из zlib (распаковывает PKWARE) Теперь это библиотека, с небольшой обёрткой, которая позволяет работать обоим алгоритмам с памятью, а не жёстким диском. Плюс к blast() добавил интерфейс, так что он теперь тоже может возвращать необходимый размер буфера для распаковки. Давно хотел такую штуку для Delphi, без всяких зависимостей от "msvcrt.dll" и прочего мусора. Также в архиве программа-пример и два файла "deflate.dat" и "pkware.dat" на которых можно потренироваться. Через дефайны: NO_DEFLATE или NO_PKWARE можно убрать ненужные алгоритмы, для уменьшения размера. |
-=CHE@TER=- |
Dec 11 2017, 12:54
Сообщение
#147
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Прошло 10 лет с момента. Посмотрел я снова Lazarus, последнюю версию - 1.8.0 (5-го декабря, кстати, вышла). Для теста взял один не очень большой и сложный проект на Delphi 7. Сконвертировался он нормально, но поглядев как работает я всё равно продолжаю офигевать от этого ужаса:
- .EXE файлы по прежнему толстые: проект в Delphi 7 был 500 Кб, здесь - 2 Мб, и это с включённой в опциях проекта оптимизацией по размеру и отключённой отладочной информацией (без них будут десятки мегабайт); - не смотря на то что проект сконвертировался без проблем, в FPC / Lazarus у TJPEGImage нет метода DIBNeeded, на что мне сразу вышибло ошибку - прозреваю, что это не единственная несовместимость; - контрол TImage так за 10 лет и не починили (долбанный стыд!) - достаточно провести по нему мышкой, чтобы он начал ужасно, чудовищно и вырвиглазно моргать и перерисовываться (хотя в изображение никаких изменений не вносилось); - все строки в UTF-8 (почему-то ключ в настройках проекта об использовании ANSIString игнорируется), поэтому загружая файлы с русскими строчками в 1251 вы будете видеть "????" вместо них; - если у вас на компьютере стоял FPC старой версии, то сносите его перед установкой Lazarus, ибо эта скотина вместо установленного с ней 3.0.4, будет подтягивать старый, который уже стоит в системе, в результате вы ничего не сможете скомпилировать (половины юнитов не будет); - установщик никакой - ставит всё, в том числе компоненты, которые вы никогда не использовали, не используете и использовать не будете, причём вместе с исходными кодами, так что готовьте гигабайт свободного места под всё это барахло (а ещё это всё будет долго устанавливаться), ибо выбрать только то что вам нужно во время установки вы не сможете. Там ещё всякого по мелочи и хотя есть и положительные моменты, но, в целом, всё по прежнему очень грустно. |
-=CHE@TER=- |
Dec 25 2017, 17:16
Сообщение
#148
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Натолкнулся на то, что в нескольких играх используется LZSS, описанный в моём сообщении выше. Не поверите - очень популярный алгоритм. Во многих играх используется.Но, есть одно отличие MS-LZSS (Microsoft LZSS) от классического LZSS (который, похоже, используется во многих играх), без которого на выходе получится не файл, а что попало. Выложил сейчас на сайт распаковщик .GPF для Snake Battle / Змеиный бой (Gamos, 1992). Вот эти строки: CODE I:=($FFF + 1) - 16; ... J:=J + ((Len And $F0) ShL 4); Len:=(Len And $0F) + 3; Заменить такими: CODE I:=($FFF + 1) - 16 - 2; ... J:=J + ((Len And $0F) ShL 8); Len:=((Len And $F0) ShR 4) + 3; И всё. |
-=CHE@TER=- |
Feb 9 2018, 09:14
Сообщение
#149
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Только одна проблема — не хочется тратить время на вникание в код, если ты его перепишешь на Си или на Паскале с помощью допотопных AssignFile и пр. Я года с 2004 использую потоки после того как увидел, как это делается в одном из исходников основателя extractor.ru Чтобы не раздувать холивар постараюсь его сократить. У меня к тебе такие вопросы:1) Обоснуй чем потоки лучше, скажем, CreateFile() + CreateFileMapping()? Ты точно также можешь весь файл в память засунуть и делать с ним что угодно. 2) В чем проблема заменить (автозаменой даже можно), скажем, "BlockRead(fl, buffer, size);" на "stream.Read(buffer, size);"? А почему ООП вообще и потоки в частности это плохо я сейчас объяснять не буду, дабы не разводить холивар - там на отдельную большую статью хватит. Вот например - обрати внимание, ООП не последние люди критикуют, хотя некоторые, конечно, личности спорные. |
-=CHE@TER=- |
Mar 4 2018, 16:12
Сообщение
#150
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Интересная статья: Calling C From ASM In X64. Тот случай, когда технологии уже дошли до того, что нельзя вот так просто взять и что-то вызвать из ассемблера, не огребя при этом кучу проблем в ответ. Оптимизация она такая, да.
|
-=CHE@TER=- |
Mar 29 2018, 12:36
Сообщение
#151
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Товарищи! Возник интересный вопрос по поводу ключей командной строки.
Смотрите, для ключа, как правило, используется какой-то символ-префикс: -param или вот так: /param Проблемы тут ровно две: 1) Если использовать '-', тогда встаёт проблема с именем файлы начинающегося с этого символа. Я писал в этой теме уже, что это можно решить коротким именем файла (dir /B /X *.*), но это сработает только в том случае, если файл имеет длинное имя. 2) Если использовать '/' и ты пишешь кроссплатформенную утилиту на сях, то этот символ является вполне себе разрешённым, ибо в иксах вместо '\' для разделения путей используется именно что '/' и путь '/usr/vasia/myfile' - это обычное дело. А идея использовать запрещённые символы в имена файла в качестве префикса - никуда не годится. Потому что в Windows они такие: \ / : * ? " < > | \ и / - используются для указания путей ('/' в Windows fopen и прочие иксовые функции перед использованием разворачивают в '\'); : - используется для указания потока у файла в NTFS дисках (кстати говоря, ещё и не является запрещённым символам в имени файла в иксах); * и ? - используются для задания маски у имени файлов, а * в иксах и того хуже - если globe не отключён, то вызов "tool *" приведёт к тому, что все файлы в текущем каталоге буду сконвертированнны в аргументы argv (аналог ParamStr в Delphi); " - используется для экранирования параметров содержащих пробел или символ табуляции; < и > используются для перенаправления ввода и вывода; | - используется для конвеера. Вариантов решения, как я понимаю, немного: 1) Если у программы один обязательный входной параметр имя файла, то жёстко делать его первым, а все остальные необязательные ключи 2, 3 и т.д. так что там можно и '-' использовать и совсем без префикса. 2) Использовать ужасное с двумя минусами '--param' как в некотрых иксовых утилитах. 3) Ещё один линуксовый подход - все параметры должны предворяться ключами, т.е. нельзя написать: tool input.dat -deflate output.dat а нужно обязательно писать громоздкое: tool -input=input.dat -method=deflate -output=output.dat У кого-нибудь ещё идеи и предложения есть? Может я что-то забыл? |
Grom PE |
Mar 29 2018, 16:38
Сообщение
#152
|
Advanced Member Группа: CTPAX-X Сообщений: 84 Регистрация: 7-February 08 Из: i@grompe.org.ru Пользователь №: 3,120 Спасибо сказали: 95 раз(а) |
Проблемы с файлами, начинающимися с "-" в винде как таковой нет, потому что маски файлов подставляются программой, а не исполняющей средой, и нет опасности, что при вызове команды "myprog *" встанет файл, превратившийся в ключ "уничтожить всё".
Лично я предпочитаю, чтоб ключи начинались с "-". Если очень надо файл "-something.txt", можно его указать программе как "?something.txt*. Проблема тут может быть в том, что в программах, обрабатывающих только один файл, авторы часто забывают сделать раскрытие масок. А в линуксах для одиночного файла принято использовать stdin/stdout, что тоже обходит проблему с минусовым файлом. (добавлено:) А, можно же ещё относительно текущей директории указывать: ".\-something.txt" Спасибо сказали:
|
-=CHE@TER=- |
Mar 30 2018, 16:06
Сообщение
#153
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Проблемы с файлами, начинающимися с "-" в винде как таковой нет, потому что маски файлов подставляются программой, а не исполняющей средой, и нет опасности, что при вызове команды "myprog *" встанет файл, превратившийся в ключ "уничтожить всё". Я не помню писал тут уже или нет, опять искать лень, но если ты компилируешь в GCC и не добавил библиотеку CRT_noglob.o в команду сборки, то, например, для каталога C:\Test\ с такими файлами:something.dat myprog.exe readme.txt вызов программы: "myprog.exe *" автоматически вернёт тебе не argc = 2 argv[0] = "C:\Test\myprog.exe" argv[1] = "*" а вот такую штуку вместо этого: argc = 4 argv[0] = "C:\Test\myprog.exe" argv[1] = "something.dat" argv[2] = "myprog.exe" argv[3] = "readme.txt" Лично я предпочитаю, чтоб ключи начинались с "-". Если очень надо файл "-something.txt", можно его указать программе как "?something.txt*. Проблема тут может быть в том, что в программах, обрабатывающих только один файл, авторы часто забывают сделать раскрытие масок. Я не хочу делать обработку маски, потому что, во-первых, тупо лень, во-вторых, если это для какой-нибудь программы типа stuns, то там это бессмысленно, потому что у тебя каждый следующий файл будет затирать выходные файлы от предыдущего. Т.е. нужно будет страдать фигнёй в отдельные каталоги записывать (например образованные от имени входного файла), либо ещё что-то придумывать. Маска больше подходит к программам, где она действительно необходима - JPGStrip например.А в линуксах для одиночного файла принято использовать stdin/stdout, что тоже обходит проблему с минусовым файлом. На обработку stdin/stdout надо отдельный код писать, в отличие от разворота "*", который принудительно отключать нужно.(добавлено:) Вот же блин, а я тоже самое сделал, просто искать лень было своё прошлое сообщение, а оно оказалось последним на предыдущей странице. Почему я про длинное имя подумал, вместо этого сам не знаю (к тому же это и не работает - короткое имя тоже будет с "-" начинаться). За 1,5 года нахрен всё забыл. Но всё равно спасибо!А, можно же ещё относительно текущей директории указывать: ".\-something.txt" |
Grom PE |
Apr 4 2018, 14:00
Сообщение
#154
|
Advanced Member Группа: CTPAX-X Сообщений: 84 Регистрация: 7-February 08 Из: i@grompe.org.ru Пользователь №: 3,120 Спасибо сказали: 95 раз(а) |
но если ты компилируешь в GCC и не добавил библиотеку CRT_noglob.o в команду сборки, то [...] Ну охренеть теперь, по умолчанию идти в чужой монастырь со своим уставом — это уж слишком. Впрочем, никогда не любил GCC.вызов программы: "myprog.exe *" автоматически вернёт тебе не argc = 2 Я не хочу делать обработку маски, потому что [...] у тебя каждый следующий файл будет затирать выходные файлы от предыдущего. Поддержка маски ≠ поддержка нескольких входных файлов. Но если лень, то хозяин — барин. |
-=CHE@TER=- |
Apr 6 2018, 11:34
Сообщение
#155
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Ну охренеть теперь, по умолчанию идти в чужой монастырь со своим уставом — это уж слишком. Впрочем, никогда не любил GCC. Ты чего такой злой? (*улыбается*) GCC - нативный компилятор для иксов. Я понимаю что, возможно, ты кроссплатформенностью не особо заморачиваешься, но мне в принципе было интересно обсудить возможное универсальное решение.Поддержка маски ≠ поддержка нескольких входных файлов. Но если лень, то хозяин — барин. На мой взгляд поддержка нескольких входных файлов ещё более уродская, чем маска (особенно, если их много). И это всё равно не снимает вопроса о выходных файлах. |
Grom PE |
Apr 6 2018, 14:21
Сообщение
#156
|
Advanced Member Группа: CTPAX-X Сообщений: 84 Регистрация: 7-February 08 Из: i@grompe.org.ru Пользователь №: 3,120 Спасибо сказали: 95 раз(а) |
Я понимаю что, возможно, ты кроссплатформенностью не особо заморачиваешься, но мне в принципе было интересно обсудить возможное универсальное решение. Кроссплатформенность — это хорошо и правильно. Но в случае с GCC, как и с другими особенно юниксово-идеологическими вещами, под кроссплатформенностью почему-то понимается не подстроиться под новую исполняемую среду, а притащить пол-юникса за собой, частью чего вот такая внезапная подстановка "*" и является. И такой подход вызывает отвращение.Спасибо сказали:
|
-=CHE@TER=- |
Jun 9 2018, 15:49
Сообщение
#157
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Мне сегодня "не баг, а фича" стандартных библиотечных сишных функций мозг выедала.
Суть: 1) Открываем файл на чтение-запись: fopen("filename.ext", "rb+") 2) Читаем что-то, меняем и тут же пишем назад: fread(buf, sz, 1, fl); // прочитали fseek(buf, -sz, SEEK_CUR); // вернулись назад fwrite(buf, sz, 1, fl); // записали 3) Повторяем в цикле пару раз. 4) Получаем на выходе хрень вместо файла. Чтобы это пофиксить, нужно либо: а) В п.1 сразу после открытия файла делать setbuf(fl, NULL) чтоб отключить буферизацию. б) Либо в п.2 после записи добавить, например: fseek(fl, 0, SEEK_CUR); // сбрасываем внутренние флаги состояния Потому что: QUOTE When the "r+", "w+", or "a+" access type is specified, both reading and writing are enabled (the file is said to be open for "update"). However, when you switch from reading to writing, the input operation must encounter an EOF marker. If there is no EOF, you must use an intervening call to a file positioning function. The file positioning functions are fsetpos, fseek, and rewind. When you switch from writing to reading, you must use an intervening call to either fflush or to a file positioning function. (с) MSDN - fopen, _wfopenВ Borland Turbo C под DOS та же фигня, кстати. А я уже было думал, что баг в винде нашёл, но это, оказывается, дофига не интуитивные сишные функции. А что, в структуре FILE нельзя было поле предусмотреть для сохранения состояния последней операции и сбрасывать внутренние флаги, если операции различаются? Риторический вопрос. |
-=CHE@TER=- |
Nov 27 2018, 12:28
Сообщение
#158
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Я тут просто охреневаю с происходящего. Короче, понадобилось мне скомпилять на сях одну либу, которая использовала функции из Windows DDK. Мой обычный способ для этого не канал, ибо ключ -ansi вызывал в одном из заголовочных файлов DDK кучу ошибок, так что я быстро накатал .BAT файл:
gcc -Wall -pedantic test.c где упомянутые два ключа должны были спасти меня от всевозможных глупых ошибок, которые я мог в процессе написания сделать. Да?.. Хрен там! Как бы не так! Когда нашёл ошибку, то вытащил функцию в отдельный файл и скопилировал уже с ключами: gcc -Wall -pedantic -ansi test.c но предупреждение всё равно не появилось! Скомпилировал тестовый файл обычным способом - и вот оно, пожалуйста. Начал убирать ключи по одному, пока не выяснилось что минимальный набор ключей, для того чтобы предупреждение наконец-то появилось, должен быть таким: gcc -Wall -Os test.c Кто не знает или забыл: -Wall - показывать предупреждение о любых некорректно написанных вещаях, даже самых незначительных -pedantic - ваще-ваще показывать сообщения обо всём и придираться ко всему -ansi - использовать стандарт C89 для компиляции (более жёсткий, чем остальные) -Os - оптимизировать генерируемый код по размеру Как оптимизация по размеру выкидывает предупреждение, которое должен был кидать компилятор?! Почему оно, вообще, там? Причём это предупреждение выводится на любом уровне оптимизации, кроме нулевого -O0 (без оптимизации). Заглядываем в документацию: QUOTE -O0 Понятно что по умолчанию и уменьшает время компиляции, но, блин, я же не хочу время компиляции уменьшить, я явно указал все ключи какие были, чтобы мне ошибки выводились! Я специально это указал - при чём тут оптимизация?Reduce compilation time and make debugging produce the expected results. This is the default. Можете со мной поспорить, но не инициализируемое значение возвращаемое из функции - это ошибка которую должен компилятор ловить, а не оптимизатор. И уж тем более эта ошибка обязана ловиться, если включены режимы -Wall или -pedantic - т.е. когда ты явно сказал, что тебе пофиг на скорость компиляции, ты хочешь чтобы проверялось всё. Кому интересно, код тестовой программы с комментариями ниже. CODE /* MinGW GCC 3.2 no warnings, no errors: > gcc -Wall -ansi -pedantic test.c only this one shows the warning: > gcc -Wall -ansi -pedantic -Os test.c > test.c: In function `func': > test.c:15: warning: `b' might be used uninitialized in this function */ #include <stdio.h> #include <time.h> int func(int a) { time_t b; /* b = 0;*/ /* accidentally forgotten line of code */ if ((a >= 0) && (a <= 59)) { b = time(NULL); } return(b); } int main(void) { printf("%d", func(-1)); return(0); } |
-=CHE@TER=- |
Jan 29 2020, 14:30
Сообщение
#159
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Кто знает, что будет выведено на экран в этих двух программах?
CODE #include <stdio.h> #include <string.h> int main(void) { char s[10]; int i; strcpy(s, "123456789"); for (i = 0; i < strlen(s); i++) { printf("%c", s[i]); s[5] = 0; } return(0); } CODE program test; {$APPTYPE CONSOLE} var s: string; i: integer; begin s:='123456789'; for i:=1 to Length(s) do begin Write(s[i]); SetLength(s, 5); end; end. Код можно переписать короче: CODE #include <stdio.h> int main(void) { int i, j; j = 9; for (i = 1; i <= j; i++) { printf("%c", '0' + i); j = 5; } return(j); /* do not optimize j = 5 */ } CODE program test; {$APPTYPE CONSOLE} var i, j: integer; begin j:=9; for i:=1 to j do begin Write(Chr(Ord('0') + i)); j:=5; end; Halt(j); (* remove warning about unused j:=5 *) end. Узнать ответ |
-=CHE@TER=- |
Jun 23 2020, 13:36
Сообщение
#160
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Пацаны! Глядите, чего я в одной книжке 1999 года по Pascal нашёл (в Delphi, во всяком случае 7-ом, тоже работает):
CODE program test; Кто знает, что будет выведено без компиляции?{$APPTYPE CONSOLE} var s: string(.4.); begin s:='TEST'; s(.1.):='W'; writeln(s); readln; end. Ну и, собственно, подсказка: (. = [ .) = ] Я знал, что в Pascal / Delphi, есть два способа многострочных комментариев: { ... } - обычный (* ... *) - дополнительный Второй способ пригодится когда нужно закомментарить большой кусок кода, где уже есть обычный. Хотя, это можно было бы сделать и так: {$IFDEF NEVER} ... {$ENDIF} Но я не знаю с какой версии в Pascal появились директивы IFDEF и ENDIF, так что, возможно, на каком-то этапе это было оправдано, особенно с учётом того, что в Pascal изначально не было строчных комментариев // как в Delphi, поэтому закомментаривать куски кода с уже какими-то комментариями внутри было проблематично. Но вот хоть ты тресни я никак не могу понять зачем мог понадобиться второй способ указания индекса у массивов. Наверняка причины тоже какие-нибудь исторические, но чем они обоснованы были придумать не смог. Если кто знает - напишите, ибо я понятия не имею как этот способ указания индекса гуглить. Предположу, что, возможно, в первых версиях языка или на старых клавиатурах не было квадратных скобок, а как-то отличать аргументы функций, типа work(1), от аргументов массива, типа list(.1.), надо было. |
Упрощённая версия | Сейчас: 1st November 2024 - 16:28 |