23:44
Untitled [457]
...у него был чёрный пояс по радиоэлектронной борьбе.
Комментарии (2)
22:37
Untitled [456]
Если на вопрос, почему ты туда-то и туда-то не придёшь, ответ "не хочу" собеседник не принимает или начинает допытываться "почему не хочешь", можно сказать, что у тебя на это время назначен приём у психиатра.
Удивительную вещь встретил. Передаю в функцию указатель на экземпляр структуры, а приходит вместо исходных значений -- мусор.
Смотрю, адреса в памяти совпадают, т.к. указатель передался правильно. Смотрю значения в памяти -- не меняются. Так почему же я передаю одни значения, а получаю другие?
Значит, они по-разному интерпретируются! Но структура одна же. Я включил её определение в .h файле в два .c файла -- в главный файл и в файл с определением функции, которую я вызываю.
Я попробовал поменять типы данных с однобайтных на двухбайтные. И оказалось, что теперь половина значений доходит правильно, но располагается в других переменных!
Короче говоря, дело было в выравнивании данных в памяти. В главном файле где-то в начале (или в одном из заголовков) было установлено #pragma pack(2), а во втором файле -- #pragma pack(4). И уже ПОСЛЕ этого был включен мой заголовочный файл и описанием структуры. В итоге главный файл думал, что выравнивать поля надо по 2 байта на переменную, а второй файл, что по четыре! Т.е. структуры имели одинаковое имя, но были несовместимы двоично! Я непосредственно перед описанием структуры в заголовочном файле поставил #pragma pack(4) и всё стало зашибись.
(пример, иллюстрирующий #pragma pack для тех, кто не в курсе)
Смотрю, адреса в памяти совпадают, т.к. указатель передался правильно. Смотрю значения в памяти -- не меняются. Так почему же я передаю одни значения, а получаю другие?
Значит, они по-разному интерпретируются! Но структура одна же. Я включил её определение в .h файле в два .c файла -- в главный файл и в файл с определением функции, которую я вызываю.
Я попробовал поменять типы данных с однобайтных на двухбайтные. И оказалось, что теперь половина значений доходит правильно, но располагается в других переменных!
Короче говоря, дело было в выравнивании данных в памяти. В главном файле где-то в начале (или в одном из заголовков) было установлено #pragma pack(2), а во втором файле -- #pragma pack(4). И уже ПОСЛЕ этого был включен мой заголовочный файл и описанием структуры. В итоге главный файл думал, что выравнивать поля надо по 2 байта на переменную, а второй файл, что по четыре! Т.е. структуры имели одинаковое имя, но были несовместимы двоично! Я непосредственно перед описанием структуры в заголовочном файле поставил #pragma pack(4) и всё стало зашибись.
(пример, иллюстрирующий #pragma pack для тех, кто не в курсе)
(развернуть список моих статей по Pixel Dungeon и форкам)
Надо было сделать одну статью по новому Ремиксу и описать в нём трёх боссов -- этого, Королеву Пауков и Лича, но этот босс достоин отдельной статьи.
(как убить Владыку Теней)
Надо было сделать одну статью по новому Ремиксу и описать в нём трёх боссов -- этого, Королеву Пауков и Лича, но этот босс достоин отдельной статьи.
(как убить Владыку Теней)
23:59
Коктейль
Еду с челом на машине.
Он: О, -10. Как раз незамерзайка на -10 замёрзла.
Я: А зачем же ты налил на -10?
Он: Да я купил на -20, вот понемногу доливаю в эту...
Я:
.
.
.
Он: О, -10. Как раз незамерзайка на -10 замёрзла.
Я: А зачем же ты налил на -10?
Он: Да я купил на -20, вот понемногу доливаю в эту...
Я:
.
.
.
Комментарии (3)
23:54
? // Эпос о Гильгамеше
Чем-то привлекают произведения из глубины веков. Данное произведение -- не самое древнее сохранившееся, но одно из самых древних. Глубже почти некуда. Написано клинописью на глиняных табличках. И бесполезно представлять себе на месте Гильгамеша одноимённого гражданина из, скажем, Fate/Stay Night, одетого в средневековый доспех. Потому что в те ещё годы даже с простыми шлемами была напряжёнка. А было это в районе 3 тысячелетия до н.э.
Основная проблема данного произведения в том, что оно плохо сохранилось. И тут я пою хвалебную песню т.н. "эпическим повторам", когда одни и те же отрывки повторяются в тексте многократно, поэтому когда на табличке невозможно прочитать слово -- или кусок таблички вообще отвалился -- по дублированным местам можно восстановить, что там было. В том числе, отрывок жалобы Гильгамеша на страх смерти в 10 табличке повторяется трижды (или даже больше), но ни разу не сохранился целиком. Однако сопоставление позволяет восстановить текст почти целиком. Несмотря на это, на текущий момент учёные "собрали" где-то 2/3 текста (это страниц 80 стихами в одну колонку). Но сборка продолжается. Некоторые места известны только в пересказе.
Также любопытно, как сделано, чтобы таблички не путались. В конце каждой таблички присутствует первая строка следующей. Это же указатель! То есть, фактически, такие широко применимые в наши дни компьютерные технологии, как помехозащищённое кодирование методом дублирования, а также однонаправленный список в памяти, были изобретены очень давно.
Главная трудность при чтении -- непонятность некоторых моментов без пояснения переводчика. Когда их прочитаешь -- становится понятно, что, к примеру, в 12 таблице Энкиду спустился в преисподнию за барабанными палочками, будучи живым ещё. А пока не прочитал, думал, что его Гильгамеш наставляет перед смертью (12 таблица вообще выбивается из основного повествования). И хотя в данном эпизоде вариантов нет, в некоторых других я думал, а не ДОДУМАЛ ли переводчик СМЫСЛ? Например, одна из самых главных мыслей произведения, это то, что Гильгамеш в конце отступился от своей цели. Но в тексте она помечена курсивом (т.е. является интерполяцией). И если почти все остальные интерполяции либо неважны с точки зрения смысла, либо восстанавливаются по повторениям/контексту, то откуда взялось именно такое восстановление, непонятно.
Хотя г-н Дьяконов, переводчик, пишет, что это типа гениальное произведение, об'единяющее известные мифы в слитный сюжет, чтобы показать главную философскую идею (о человеческой смертности), у меня было ощущение неровности повествования. Тем не менее, некоторые эпизоды весьма впечатляют. Во-первых, это первая таблица, о том, как некоего Энкиду, доисторического Маугли, выманили из общества диких животных при помощи обнажённой женщины, а потом приучили его к культуре (доисторической, но всё равно культуре). Во-вторых, это история с небесным быком. Её я, пожалуй, перескажу подробнее.
Иштар -- девка ещё та.
Основная проблема данного произведения в том, что оно плохо сохранилось. И тут я пою хвалебную песню т.н. "эпическим повторам", когда одни и те же отрывки повторяются в тексте многократно, поэтому когда на табличке невозможно прочитать слово -- или кусок таблички вообще отвалился -- по дублированным местам можно восстановить, что там было. В том числе, отрывок жалобы Гильгамеша на страх смерти в 10 табличке повторяется трижды (или даже больше), но ни разу не сохранился целиком. Однако сопоставление позволяет восстановить текст почти целиком. Несмотря на это, на текущий момент учёные "собрали" где-то 2/3 текста (это страниц 80 стихами в одну колонку). Но сборка продолжается. Некоторые места известны только в пересказе.
Также любопытно, как сделано, чтобы таблички не путались. В конце каждой таблички присутствует первая строка следующей. Это же указатель! То есть, фактически, такие широко применимые в наши дни компьютерные технологии, как помехозащищённое кодирование методом дублирования, а также однонаправленный список в памяти, были изобретены очень давно.
Главная трудность при чтении -- непонятность некоторых моментов без пояснения переводчика. Когда их прочитаешь -- становится понятно, что, к примеру, в 12 таблице Энкиду спустился в преисподнию за барабанными палочками, будучи живым ещё. А пока не прочитал, думал, что его Гильгамеш наставляет перед смертью (12 таблица вообще выбивается из основного повествования). И хотя в данном эпизоде вариантов нет, в некоторых других я думал, а не ДОДУМАЛ ли переводчик СМЫСЛ? Например, одна из самых главных мыслей произведения, это то, что Гильгамеш в конце отступился от своей цели. Но в тексте она помечена курсивом (т.е. является интерполяцией). И если почти все остальные интерполяции либо неважны с точки зрения смысла, либо восстанавливаются по повторениям/контексту, то откуда взялось именно такое восстановление, непонятно.
Хотя г-н Дьяконов, переводчик, пишет, что это типа гениальное произведение, об'единяющее известные мифы в слитный сюжет, чтобы показать главную философскую идею (о человеческой смертности), у меня было ощущение неровности повествования. Тем не менее, некоторые эпизоды весьма впечатляют. Во-первых, это первая таблица, о том, как некоего Энкиду, доисторического Маугли, выманили из общества диких животных при помощи обнажённой женщины, а потом приучили его к культуре (доисторической, но всё равно культуре). Во-вторых, это история с небесным быком. Её я, пожалуй, перескажу подробнее.
Иштар: Гильгамеш, давай жениться!
Гильгамеш: Неее. Ты всех своих предыдущих любовников кого сгубила, кого что, а теперь ещё и за меня возьмёшься?
Иштар: Папа, он меня обижает! Сделай мне быка, который бы его убил!
Ану: От тебе бык и отстань от меня уже.
Иштар: Теперь ты у меня попляшешь, Гильгамеш!
Гильгамеш: Энкиду, пошли мочить быка.
Энкиду: ок.
*мочат быка*
Энкиду: Эй, Иштар, мы твоего быка замочили! Я бы с тобой то же самое сделал, если бы мог добраться...
Иштар: Папа, папа!
Иштар -- девка ещё та.
Комментарии (2)
23:56
Untitled [455]
Романтические углеводороды.
Комментарии (2)
23:56
Рука-мобильник
Проспал будильник.
Но уже через 15 минут раздался телефонный звонок на городской телефон. Я поднял трубку.
Я: Алло.
Телефон: ...
Я: Алло.
Телефон: ...
Я: Алло...
Телефон: ...
Я: ...
Телефон: Goodbye... (незнакомый женский голос с хорошим английским произношением)
(короткие гудки)
Так я не проспал работу...
Но уже через 15 минут раздался телефонный звонок на городской телефон. Я поднял трубку.
Я: Алло.
Телефон: ...
Я: Алло.
Телефон: ...
Я: Алло...
Телефон: ...
Я: ...
Телефон: Goodbye... (незнакомый женский голос с хорошим английским произношением)
(короткие гудки)
Так я не проспал работу...
Комментарии (1)
23:59
О тетрисе в мю-торрент
Не все знают, что в мю-торренте есть тетрис. Про него я как-то писал. Рассказываю коллеге -- он не знал.
Заходит по удалёнке на свой домашний комп, жмёт t в окошке About -- ничего не происходит. Меняет раскладку -- то же.
Думаю, может в новых версиях это убрали?
Захожу по удалёнке на свой домашний комп, жму t в окне About -- ничего не происходит. Меняю раскладку -- то же. Но у меня точно версия, где тетрис есть. В чём дело?
ОКАЗАЛОСЬ, что только если раскладка на хостовом и удалённом компах совпадает -- тогда он запускается. У нас разные программы для подключения -- TeamViewer и TightVNC.
Заходит по удалёнке на свой домашний комп, жмёт t в окошке About -- ничего не происходит. Меняет раскладку -- то же.
Думаю, может в новых версиях это убрали?
Захожу по удалёнке на свой домашний комп, жму t в окне About -- ничего не происходит. Меняю раскладку -- то же. Но у меня точно версия, где тетрис есть. В чём дело?
ОКАЗАЛОСЬ, что только если раскладка на хостовом и удалённом компах совпадает -- тогда он запускается. У нас разные программы для подключения -- TeamViewer и TightVNC.
23:58
MLG
Было время, когда я проходил Half Life 2 Episode 1. Это что-то вроде дополнения к Half Life 2, но представляло собой законченную короткую игру.
И вот я играю, играю. И замечаю, что нигде нет ни аптечек, ни лечильных станций на стене. Думаю, что это странно, но ладно, мало ли, задумка разработчиков. Пришлось экономить -- по 4-5 раз проходил каждое место, чтобы минимизировать урон от врагов, а идеально -- пройти без урона.
И вот в определённом месте я застрял. Всё вокруг обходил, врагов убил, а что делать дальше -- не знаю. Вижу только -- пропасть. Через неё не перейти. На другой стороне стоит враг, но ко мне не идёт. Надо до него добраться, это ясно. Но как?
Я в него выстрелил.
И он побежал ко мне прямо через пропасть. По пустому пространству. Я его, естественно, убил, а потом пошёл по тому пустому пространству, через которое он шёл ко мне. И перешёл на другую сторону! Невидимый мост.
Я ещё раз удивился остроумию разработчиков.
А потом я случайно узнал, что мост, вообще-то, должен был быть видимым. Оказывается, у меня были битые текстуры, поэтому я не видел аптечек, лечильных станций и моста. Я к тому времени прошёл уже больше 2/3 эпизода.
Впрочем, идея невидимости в играх применяется на самом деле. В Dark Souls 1 и в Lab14 есть невидимые мосты, а в Dark Souls 2 -- невидимые враги и лестницы.
И вот я играю, играю. И замечаю, что нигде нет ни аптечек, ни лечильных станций на стене. Думаю, что это странно, но ладно, мало ли, задумка разработчиков. Пришлось экономить -- по 4-5 раз проходил каждое место, чтобы минимизировать урон от врагов, а идеально -- пройти без урона.
И вот в определённом месте я застрял. Всё вокруг обходил, врагов убил, а что делать дальше -- не знаю. Вижу только -- пропасть. Через неё не перейти. На другой стороне стоит враг, но ко мне не идёт. Надо до него добраться, это ясно. Но как?
Я в него выстрелил.
И он побежал ко мне прямо через пропасть. По пустому пространству. Я его, естественно, убил, а потом пошёл по тому пустому пространству, через которое он шёл ко мне. И перешёл на другую сторону! Невидимый мост.
Я ещё раз удивился остроумию разработчиков.
А потом я случайно узнал, что мост, вообще-то, должен был быть видимым. Оказывается, у меня были битые текстуры, поэтому я не видел аптечек, лечильных станций и моста. Я к тому времени прошёл уже больше 2/3 эпизода.
Впрочем, идея невидимости в играх применяется на самом деле. В Dark Souls 1 и в Lab14 есть невидимые мосты, а в Dark Souls 2 -- невидимые враги и лестницы.
Комментарии (9)
23:36
Фейл-моногатари [05]
В прошивке контроллера написано выдавать сигнал на выход, а осциллограф этого не видит. Никак не мог понять, в чём дело.
Решил -- контроллер работает на частоте 200 МГц. Возможно, сигнал проскакивает так быстро, что осциллограф просто не срабатывает? (он работает в режиме single sequence: при появлении сигнала он начинает измерение данных, а потом показывает статичную картинку начиная с момента появления сигнала)
Думаю, надо для теста уменьшить частоту. Так, какие у нас ещё есть источники для тактовой частоты? О, тактовый генератор 32 кГц! Его и поставлю!
И заменил строчку:
REGISTERS->PERIPHERAL_CLOCK=9<<24;//основной кварцевый генератор; в 24-28 битах должна быть 9,
//остальные биты 0; << -- логический побитовый сдвиг влево.
На строчку:
REGISTERS->PERIPHERAL_CLOCK=1<<24;//генератор 32 кГц на RC-цепочке
Контроллер после этого прошился, но при попытке выполнить пару строк кода завис. И больше он теперь не прошивается!
Решил -- контроллер работает на частоте 200 МГц. Возможно, сигнал проскакивает так быстро, что осциллограф просто не срабатывает? (он работает в режиме single sequence: при появлении сигнала он начинает измерение данных, а потом показывает статичную картинку начиная с момента появления сигнала)
Думаю, надо для теста уменьшить частоту. Так, какие у нас ещё есть источники для тактовой частоты? О, тактовый генератор 32 кГц! Его и поставлю!
И заменил строчку:
REGISTERS->PERIPHERAL_CLOCK=9<<24;//основной кварцевый генератор; в 24-28 битах должна быть 9,
//остальные биты 0; << -- логический побитовый сдвиг влево.
На строчку:
REGISTERS->PERIPHERAL_CLOCK=1<<24;//генератор 32 кГц на RC-цепочке
Контроллер после этого прошился, но при попытке выполнить пару строк кода завис. И больше он теперь не прошивается!
Комментарии (4)
23:18
Untitled [454]
Сестра рассказывает сказку о трёх братьях из Гарри Поттера.
Сестра: И вот они построили мост, входят на него, тут перед ними появляется фигура в плаще...
Я: И говорит "ТЫ НЕ ПРОЙДЁШЬ!"
Сестра: И вот они построили мост, входят на него, тут перед ними появляется фигура в плаще...
Я: И говорит "ТЫ НЕ ПРОЙДЁШЬ!"
22:48
Чёрный гроб на колёсиках
Много раз я видел в метро людей, катящих за собой специальный чемодан на маленьких колёсиках с выдвижной ручкой (ручка у чемодана, а не у колёсиков). Мне всегда казалось смешным то, как люди останавливаются перед лестницей, берут его за ручку (но не выдвижную, а другую) и несут по лестнице на руках.
Сегодня я встретил маму из поездки и получил шанс покатать такой чемодан самостоятельно. До этого я катал телеги только грузовые (советские), с диаметром колёс от 15 см (и загрузкой от 25 кг).
То, что я напишу ниже, безусловно, является выводом, сделанным по одному измерению. Может быть, есть где-то и хорошие чемоданы-тележки.
1. Опыт спуска и под'ёма грузовых телег по лестнице тут бесполезен. Из-за малого диаметра колёс сама сумка цепляет за ступеньки. Остаётся действительно только одно -- взять за ручку и нести.
2. Не только малый диаметр колёс, но и малое расстояние между ними делают бесполезным понатыканные всюду пандусы. Даже если бы расстояние между колёсами было больше на 10-15 см, воспользоваться пандусами не вышло бы всё равно, т.к. большинство пандусов -- с высокими бортиками (П-образный профиль), которые больше, чем расстояние от окружности колеса до поверхности сумки. Также малое расстояние между колёсами придаёт телеге просто божественную устойчивость -- резкий поворот или старт с места -- и телега заваливается на бок.
3. Дело ещё в малом расстоянии от окружности колеса до арки колеса. Я не разглядывал, сколько там, то эта щель забивается мгновенно -- уличной грязью, песком, рассыпанным коммунальщиками, и снегом. После этого тележка уже не катит. В прямом смысле.
Эти телеги-чемоданы предназначены для катания даже не в городских условиях, а исключительно по специальному тележкодрому, там где всё чисто и ровно.
Сегодня я встретил маму из поездки и получил шанс покатать такой чемодан самостоятельно. До этого я катал телеги только грузовые (советские), с диаметром колёс от 15 см (и загрузкой от 25 кг).
То, что я напишу ниже, безусловно, является выводом, сделанным по одному измерению. Может быть, есть где-то и хорошие чемоданы-тележки.
1. Опыт спуска и под'ёма грузовых телег по лестнице тут бесполезен. Из-за малого диаметра колёс сама сумка цепляет за ступеньки. Остаётся действительно только одно -- взять за ручку и нести.
2. Не только малый диаметр колёс, но и малое расстояние между ними делают бесполезным понатыканные всюду пандусы. Даже если бы расстояние между колёсами было больше на 10-15 см, воспользоваться пандусами не вышло бы всё равно, т.к. большинство пандусов -- с высокими бортиками (П-образный профиль), которые больше, чем расстояние от окружности колеса до поверхности сумки. Также малое расстояние между колёсами придаёт телеге просто божественную устойчивость -- резкий поворот или старт с места -- и телега заваливается на бок.
3. Дело ещё в малом расстоянии от окружности колеса до арки колеса. Я не разглядывал, сколько там, то эта щель забивается мгновенно -- уличной грязью, песком, рассыпанным коммунальщиками, и снегом. После этого тележка уже не катит. В прямом смысле.
Эти телеги-чемоданы предназначены для катания даже не в городских условиях, а исключительно по специальному тележкодрому, там где всё чисто и ровно.
Комментарии (6)
23:54
Собака Маруся
Мама говорит -- а пошли на выставку Рафаэля в Пушкинский. И мы все пошли.
Выставка была не очень интересная. Картин мало. Людей со значками черепашек-ниндзя замечено не было. Но две вещи поразили:
1. Этому, блин, куску бумаги, 500 лет!
2. А в 16 веке картины рисовали на доске.
Гораздо интереснее было изображение, обнаруженное мной в музейном киоске:
А ещё там же была выставка картин для слепых -- выпуклые репродукции. Стоим с сестрой, щупаем. Подходит девушка -- вы знаете, эта выставка для незрячих...
Я (смотрю на неё): Знаем.
А ещё там же была выставка "обстановка немецкого дома 18 века". И всякие бытовые предметы. Стоит туфля одна. Экспонат подписан. "Полупара туфель"! То есть это не просто туфля, это полупара, видите ли!
Выставка была не очень интересная. Картин мало. Людей со значками черепашек-ниндзя замечено не было. Но две вещи поразили:
1. Этому, блин, куску бумаги, 500 лет!
2. А в 16 веке картины рисовали на доске.
Гораздо интереснее было изображение, обнаруженное мной в музейном киоске:
А ещё там же была выставка картин для слепых -- выпуклые репродукции. Стоим с сестрой, щупаем. Подходит девушка -- вы знаете, эта выставка для незрячих...
Я (смотрю на неё): Знаем.
А ещё там же была выставка "обстановка немецкого дома 18 века". И всякие бытовые предметы. Стоит туфля одна. Экспонат подписан. "Полупара туфель"! То есть это не просто туфля, это полупара, видите ли!
23:55
Untitled [453]
К нам пришёл для переговоров гражданин из дружественной организации.
Коллега: Кофе будешь?
Гражданин: Нет. Я с детства кофе не пью...
Я: А до детства значит пил?
Гражданин: Да.
О_о
Коллега: Кофе будешь?
Гражданин: Нет. Я с детства кофе не пью...
Я: А до детства значит пил?
Гражданин: Да.
О_о
Комментарии (1)
23:55
Зазеркалье
С детства нас учат правильно выбирать тип переменной. Например, если числа она должна представлять только положительные, её можно сделать типа unsigned int -- тогда она сможет представить в два раза больший набор значений.
Итак, в одном из проектов у нас есть маленький модуль. Он реализует обработку команд на специальном птичьем языке програмирования. Он был придуман давным-давно, ещё до моего прихода в нашу организацию. Этот язык не поддерживает условия, но поддерживает циклы. Перед выполнением циклы "разворачиваются", в итоге получается фиксированная последовательность команд без переходов, которая исполняется последовательно.
То есть, до разворачивания макрос выглядел так:
loop 3
command1
command2
endloop
А после разворачивания так:
nop
command1
command2
nop
nop
command1
command2
nop
nop
command1
command2
nop
По тактическим соображениям команды начала и конца цикла не удалялись, а заменялись на nop (пустая команда).
Циклы поддерживались только одного уровня вложенности, в то время как существовала необходимость сделать циклы минимум вложенности 2. Это задание было выдано мне. Я решил сразу делать цикл вложенности n. Как определять границы циклов -- плёвая задача. В итоге я написал функцию:
void Unfold(CMacros *pMacros, unsigned int nStart, unsigned int nEnd);
Она должна была брать макрос pMacros, извлекать из него заданный набор команд -- от номера nStart до номера nEnd -- повторять их заданное число раз (тут этот момент опущен) и вставлять после первого встречания тела цикла. Там было написано примерно следующее:
InsertAt -- вставляет в заданную позицию, сдвигая то, что там было (и всё дальнейшее), дальше по массиву.
aCommands -- массив команд.
GetAt -- обращение к массиву по заданному индексу.
Эта штука работала без нареканий 2 года. Но сегодня ружьё выстрелило. Программа падает. Почему? Выход за границы массива в GetAt.
ОКАЗАЛОСЬ, что nStart равен нулю. Два года работы, десятки скриптов. Ни у одного из них начало цикла не было первой командой! Поэтому значение типа unsigned int (переменная x) всегда сравнивалось с числом 1 или больше (очевидно, первая команда имела номер 0, а не 1). И когда оно становилось равно в худшем случае нулю, цикл прекращался. Когда же цикл оказался стоящим первой командой, возникла прикольная ситуация. Число типа unsigned всегда будет больше либо равно нуля! Если из него вычесть 1, оно станет равно 2^32-1 (если int 32 бита). Перенос! И по этому четырёхмиллиардному смещению программа пытается что-то там прочитать.
Я смотрю на это и говорю -- а давайте поменяем тип x на int. Тогда он станет равным -1, а -1>=0 это ложь. Т.к. условие в цикле for проверяется ДО тела, то цикл завершится ещё до того, как -1 попадёт в аргумент GetAt.
Сделали. Но не помогло. Происходил вход в тело цикла! Тогда мы заменили nStart и nEnd тоже на просто int -- и всё заработало!
Что это означает? Что при проверке условия x>=nStart по неизвестной причине int преобразуется к unsigned int, а не наоборот! И -1 при сравнении превращалась в ту же 2^32-1 или может и во что похуже, но это значения не имеет, т.к. оно было типа unsigned int, а любое число этого типа будет заведомо больше либо равно нулю.
Мораль. Не использовать тип unsigned в циклах с обратным счётом. Тут такой цикл был нужен, чтобы вставлять команды в одну и ту же точку массива, сдвигая его конец всё дальше. Чтобы порядок команд не стал обратным, надо было запихивать их в массив задом наперёд, но по одному и тому же смещению.
Итак, в одном из проектов у нас есть маленький модуль. Он реализует обработку команд на специальном птичьем языке програмирования. Он был придуман давным-давно, ещё до моего прихода в нашу организацию. Этот язык не поддерживает условия, но поддерживает циклы. Перед выполнением циклы "разворачиваются", в итоге получается фиксированная последовательность команд без переходов, которая исполняется последовательно.
То есть, до разворачивания макрос выглядел так:
loop 3
command1
command2
endloop
А после разворачивания так:
nop
command1
command2
nop
nop
command1
command2
nop
nop
command1
command2
nop
По тактическим соображениям команды начала и конца цикла не удалялись, а заменялись на nop (пустая команда).
Циклы поддерживались только одного уровня вложенности, в то время как существовала необходимость сделать циклы минимум вложенности 2. Это задание было выдано мне. Я решил сразу делать цикл вложенности n. Как определять границы циклов -- плёвая задача. В итоге я написал функцию:
void Unfold(CMacros *pMacros, unsigned int nStart, unsigned int nEnd);
Она должна была брать макрос pMacros, извлекать из него заданный набор команд -- от номера nStart до номера nEnd -- повторять их заданное число раз (тут этот момент опущен) и вставлять после первого встречания тела цикла. Там было написано примерно следующее:
unsigned int x;
for(x=nEnd;x>=nStart;x--)
{
pMacros->aCommands->InsertAt(nEnd+1,pMacros->aCommands->GetAt(x));
}
InsertAt -- вставляет в заданную позицию, сдвигая то, что там было (и всё дальнейшее), дальше по массиву.
aCommands -- массив команд.
GetAt -- обращение к массиву по заданному индексу.
Эта штука работала без нареканий 2 года. Но сегодня ружьё выстрелило. Программа падает. Почему? Выход за границы массива в GetAt.
ОКАЗАЛОСЬ, что nStart равен нулю. Два года работы, десятки скриптов. Ни у одного из них начало цикла не было первой командой! Поэтому значение типа unsigned int (переменная x) всегда сравнивалось с числом 1 или больше (очевидно, первая команда имела номер 0, а не 1). И когда оно становилось равно в худшем случае нулю, цикл прекращался. Когда же цикл оказался стоящим первой командой, возникла прикольная ситуация. Число типа unsigned всегда будет больше либо равно нуля! Если из него вычесть 1, оно станет равно 2^32-1 (если int 32 бита). Перенос! И по этому четырёхмиллиардному смещению программа пытается что-то там прочитать.
Я смотрю на это и говорю -- а давайте поменяем тип x на int. Тогда он станет равным -1, а -1>=0 это ложь. Т.к. условие в цикле for проверяется ДО тела, то цикл завершится ещё до того, как -1 попадёт в аргумент GetAt.
Сделали. Но не помогло. Происходил вход в тело цикла! Тогда мы заменили nStart и nEnd тоже на просто int -- и всё заработало!
Что это означает? Что при проверке условия x>=nStart по неизвестной причине int преобразуется к unsigned int, а не наоборот! И -1 при сравнении превращалась в ту же 2^32-1 или может и во что похуже, но это значения не имеет, т.к. оно было типа unsigned int, а любое число этого типа будет заведомо больше либо равно нулю.
Мораль. Не использовать тип unsigned в циклах с обратным счётом. Тут такой цикл был нужен, чтобы вставлять команды в одну и ту же точку массива, сдвигая его конец всё дальше. Чтобы порядок команд не стал обратным, надо было запихивать их в массив задом наперёд, но по одному и тому же смещению.
Комментарии (4)
23:57
Мимик
Сегодня подкинули идею, как ограничить количество голосового спама по сотовому телефону.
Многие телефонные спаммеры используют открытые и закрытые базы данных, так что уже знают, как зовут "клиента". Когда звонят с неизвестного номера и спрашивают "Имя Отчество?" -- надо отвечать "нет, вы ошиблись".
Я говорю -- погоди, а что делать, если кто-то нормальный звонит? Коллега говорит -- нормальные сначала представляются.
Я стал думать -- а вот нифига. Мне кажется (со стороны звонящего) нормальным сначала проверить, туда ли я попал, а потом уже об'яснять, кто я (хотя кто сказал, что я нормальный?). Я изложил эти соображения. Коллега предлагает тогда (со стороны принимающего) СНАЧАЛА спрашивать, кто звонит, а потом уже говорить, что не туда попали.
Надо попробовать.
Многие телефонные спаммеры используют открытые и закрытые базы данных, так что уже знают, как зовут "клиента". Когда звонят с неизвестного номера и спрашивают "Имя Отчество?" -- надо отвечать "нет, вы ошиблись".
Я говорю -- погоди, а что делать, если кто-то нормальный звонит? Коллега говорит -- нормальные сначала представляются.
Я стал думать -- а вот нифига. Мне кажется (со стороны звонящего) нормальным сначала проверить, туда ли я попал, а потом уже об'яснять, кто я (хотя кто сказал, что я нормальный?). Я изложил эти соображения. Коллега предлагает тогда (со стороны принимающего) СНАЧАЛА спрашивать, кто звонит, а потом уже говорить, что не туда попали.
Надо попробовать.
Комментарии (2)
23:57
Об ответственности
Я всегда хвастался (или гордился) тем, что заранее не хочу брать на себя ответственность за что-либо, потому что типа её осознаю. И типа это гораздо лучше, чем взять на себя ответственность не понимая её -- и облажаться.
Может быть, это действительно и лучше (я до сих пор так думаю), но сильно подозреваю, что и то, и другое -- инфантилизм.
Может быть, это действительно и лучше (я до сих пор так думаю), но сильно подозреваю, что и то, и другое -- инфантилизм.
Комментарии (2)
23:59
Одним глазком
В играх серии Dark Souls (по крайней мере, в 1 и 2 частях) есть такая штука -- проход, закрытый туманом.
Когда к нему подходишь, можно пройти сквозь туман и узнать, что с другой стороны. Там либо ещё один кусок локации (и туман исчезает), либо босс (и туман остаётся висеть, пока босс не побеждён). Если за туманом босс -- обратно выйти через него нельзя. Или победа -- или "смерть через матумбу".
Проходить через туман, не зная, что с другой стороны -- страшно. Потому что есть два варианта развития событий -- и босс -- не лучший из них: обычно на этот момент уже накоплено какое-то число душ (внутриигровая валюта), которые пропадут, если погибнуть в схватке с боссом.
Мне бывает так страшно, что я даже заглядываю в прохождение, чтобы знать, что там, за туманом. В то время как существует способ бескровно проходить сквозь туман, который я постоянно использую в некоторых случаях. При проходе же через незнакомый туман -- я забываю о нём.
Можно воспользоваться одним из средств возврата к последнему костру -- косточкой возвращения, чудом "возвращение" или пером (только в дарк соулс 2). Как правило, босс не атакует в ту же секунду, а воспользоваться этим способом можно за 2-3 секунды.
Это полностью убирает проблемы с неопределённостью ситуации за туманом.
Когда к нему подходишь, можно пройти сквозь туман и узнать, что с другой стороны. Там либо ещё один кусок локации (и туман исчезает), либо босс (и туман остаётся висеть, пока босс не побеждён). Если за туманом босс -- обратно выйти через него нельзя. Или победа -- или "смерть через матумбу".
Проходить через туман, не зная, что с другой стороны -- страшно. Потому что есть два варианта развития событий -- и босс -- не лучший из них: обычно на этот момент уже накоплено какое-то число душ (внутриигровая валюта), которые пропадут, если погибнуть в схватке с боссом.
Мне бывает так страшно, что я даже заглядываю в прохождение, чтобы знать, что там, за туманом. В то время как существует способ бескровно проходить сквозь туман, который я постоянно использую в некоторых случаях. При проходе же через незнакомый туман -- я забываю о нём.
Можно воспользоваться одним из средств возврата к последнему костру -- косточкой возвращения, чудом "возвращение" или пером (только в дарк соулс 2). Как правило, босс не атакует в ту же секунду, а воспользоваться этим способом можно за 2-3 секунды.
Это полностью убирает проблемы с неопределённостью ситуации за туманом.
Книга о том, как расстрелянный в 1950 году китайский помещик Симэнь Нао перерождается в осла, вола, свинью, собаку, обезьяну и человека, следя при этом за бытовой жизнью тех, кого он знал, и их потомков, а также принимая в этой жизни участие.
Суб'ективно -- очень длинная книга. Читаешь, читаешь, читаешь, читаешь -- а края не видно.
Мо Янь -- этот паршивец -- китайский писатель. Надо сказать, что японскую литературу я читал, а вот китайскую -- нет. Делать выводы о китайской литературе по одному измерению, конечно, не следует.
Но книжка хорошая. Что в ней хорошего -- беллетристическая увлекательность, в первую очередь. Кроме того, книга даёт представление об истории Китая времён второй половины 20 века. То есть -- времён китайского коммунизма и Мао Цзедуна.
И то, как показан быт и исторический контекст Китая тех лет -- очень сильно удивляет. Блин, их коммунизм практически повторил все этапы коммунизма нашего, советского. И пришёл примерно к тому же результату.
Не очень понятно, насколько исторически достоверно всё описано. Но доверие это вызывает -- как и исландские саги. Кстати, я вижу определённое сходство исландских саг с данным романом. Оно, конечно, не абсолютное. Например, не всё содержание романа -- описаний распрей, кроме того, много описаний эмоций, а не действий (что для саг совершенно нехарактерно). Также местами описание переходит в жанр социалистического реализма и вызывает ассоциацию с "Как закалялась сталь".
Чем я остался не очень доволен -- так это концом четвёртой и всей пятой частью. Сложилось впечатление, что автору надоело писать, поэтому он решил устроить полный Уно Моменто. Тем не менее, способ описания действительности Мо Яня мне всё равно нравится -- он совмещает в себе цинизм и романтику (в широком смысле слова). А я любитель и того и другого.
Интересно, что этот паршивец Мо Янь зациклен не только на теме сексуальности (это норма!), но и на тебе кастрации. К чему бы это?..
Условной моралью произведения можно считать, что крутое существо будет крутым, в каком бы обличии оно не находилось. Симэнь Нао стал известен во всех воплощениях (может быть, кроме обезьяны) -- и добивался немалых успехов. Любопытно было бы посмотреть, чего бы он добился, перерадившись подсолнухом, к примеру.
В заключение я приведу один из отрывков из романа. Этот отрывок меня очень впечатлил. Примечание: автор включил себя (Мо Яня) в качестве одного из персонажей романа. При этом рассказчики часто ссылаются на него и приводят выдержки из различных книг, которые он якобы написал. По-видимому, большая часть этих книг не существует.
Суб'ективно -- очень длинная книга. Читаешь, читаешь, читаешь, читаешь -- а края не видно.
Мо Янь -- этот паршивец -- китайский писатель. Надо сказать, что японскую литературу я читал, а вот китайскую -- нет. Делать выводы о китайской литературе по одному измерению, конечно, не следует.
Но книжка хорошая. Что в ней хорошего -- беллетристическая увлекательность, в первую очередь. Кроме того, книга даёт представление об истории Китая времён второй половины 20 века. То есть -- времён китайского коммунизма и Мао Цзедуна.
И то, как показан быт и исторический контекст Китая тех лет -- очень сильно удивляет. Блин, их коммунизм практически повторил все этапы коммунизма нашего, советского. И пришёл примерно к тому же результату.
Не очень понятно, насколько исторически достоверно всё описано. Но доверие это вызывает -- как и исландские саги. Кстати, я вижу определённое сходство исландских саг с данным романом. Оно, конечно, не абсолютное. Например, не всё содержание романа -- описаний распрей, кроме того, много описаний эмоций, а не действий (что для саг совершенно нехарактерно). Также местами описание переходит в жанр социалистического реализма и вызывает ассоциацию с "Как закалялась сталь".
Чем я остался не очень доволен -- так это концом четвёртой и всей пятой частью. Сложилось впечатление, что автору надоело писать, поэтому он решил устроить полный Уно Моменто. Тем не менее, способ описания действительности Мо Яня мне всё равно нравится -- он совмещает в себе цинизм и романтику (в широком смысле слова). А я любитель и того и другого.
Интересно, что этот паршивец Мо Янь зациклен не только на теме сексуальности (это норма!), но и на тебе кастрации. К чему бы это?..
Условной моралью произведения можно считать, что крутое существо будет крутым, в каком бы обличии оно не находилось. Симэнь Нао стал известен во всех воплощениях (может быть, кроме обезьяны) -- и добивался немалых успехов. Любопытно было бы посмотреть, чего бы он добился, перерадившись подсолнухом, к примеру.
В заключение я приведу один из отрывков из романа. Этот отрывок меня очень впечатлил. Примечание: автор включил себя (Мо Яня) в качестве одного из персонажей романа. При этом рассказчики часто ссылаются на него и приводят выдержки из различных книг, которые он якобы написал. По-видимому, большая часть этих книг не существует.
В «Записках о свиноводстве» Мо Янь так пишет о тушах свиней, сброшенных в реку:
Более тысячи голов дохлых свиней со свинофермы «Абрикосовый сад» плыли ряд за рядом: они гнили, разбухали, лопались, их пожирали личинки, разрывали на куски рыбы, а они плыли и плыли по течению, пока наконец не исчезли в безбрежных просторах Восточного моря, где их проглотили, где они растворились, превратились в самые разные частицы великого и превечного круговорота материи.
Неплохо написал, паршивец, ничего не скажешь. Одну только возможность упустил. Случись ему увидеть, как я, Шестнадцатый, Царь свиней, с Сяо Хуа [тоже свинья -- прим. zHz] на спине плыву в тускло-золотом потоке, а за нами гонятся волны — вот тогда он не смерть живописал бы, а жизнь, превозносил бы нас, воспел бы хвалу мне! Я и есть жизненная сила, я — страсть, я — свобода, я — любовь, я — самое прекрасное, самое поразительное проявление жизни на земле.