Евгений Степанищев

Это сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

99 бутылок: препроцессор Си

Те программисты, кто каким-либо образом сталкивался с языком Си, знают, что у него есть так называемый препроцессор. Его директивы начинаются с символа решётки и выполняются до компиляции программы. Обычно его используют, чтобы включить одни файлы в другие, определить макрос или проверить значение каких-либо внутренних флагов компилятора.

С тех пор как мне много лет назад кто-то показал как можно на нём писать программы, меня не оставляла идея написать на нём «песню о пиве».

80. Препроцессор Си, разумеется, не задумывался как что-то на чём будут писать программы, поэтому, чтобы добиться цели, приходится использовать россыпь хитростей и разнообразных хаков. Не думаю, что имеет смысл их описывать, тем более не я их придумал. В интернете есть достаточно подробных статей по этой теме, как на английском, так и на русском.

Изучение этих материалов было не только для меня интересным делом, но и полезным — я лучше понял как работает препроцессор в Си, а так же узнал кое-что новое, являющееся, правда, расширением языка.

Вопреки обыкновению, вывод программы я обрабатываю другой утилитой (см. строку запуска). Это приходится делать, так как в этом языке нет простого способа вывести перевод строки. Можно было бы сделать это ANSI-кодами, но их не будет видно в листинге кода, что меня не устраивает.

#if 0
Bolknote.ru, 2024.11.05
To run:
gcc -P -E - < 99 | sed 's/\\n */\n/g'
#endif

#define CAT(a, b) a##b
#define SECOND(a, b, ...) b
#define TEST(...) SECOND(__VA_ARGS__, 0)
#define LF \n

#define DEC(n) CAT(DEC_,n)
#define DEC_0 9
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8

#define DEC_X0(a, b) IF_ELSE(ISZERO(b)) (DEC(a)) (a)

#define ISEND(a, b) TEST(ISEND_ ## a ## b)
#define ISEND_01 ,1

#define ISZERO(n) TEST(ISZERO_ ## n)
#define ISZERO_0 ,1

#define ISONE(n) TEST(ISONE_ ## n)
#define ISONE_1 ,1

#define IF_ELSE(b) CAT(IF_, b)
#define IF_0(i) ELSE_0
#define IF_1(i) i ELSE_1
#define ELSE_0(e) e
#define ELSE_1(e)

#define PLUR(n) IF_ELSE(ISONE(n)) (bottle) (bottles)

#define PRINT_PLUR(a, b) IF_ELSE(ISZERO(a)) (b PLUR(b)) (CAT(a, b) bottles)

#define PRINT_B(a, b) IF_ELSE(ISZERO(b)) \
        (IF_ELSE(ISZERO(a)) \
            (No bottles) \
            (PRINT_PLUR(a, b)) \
        ) \
        (PRINT_PLUR(a, b)) of beer

#define PRINT_ROW(a, b) \
    PRINT_B(a, b) on the wall, PRINT_B(a, b)! LF \
    Take on down, pass it around, LF \
    PRINT_B(DEC_X0(a, b), DEC(b))! LF LF


#define STOP(...) No more bottles of beer on the wall, LF \
No more bottles of beer! LF \
Go to the store and buy some more, LF \
PRINT_B(9, 9) on the wall!

#define EMPTY()
#define DEFER(...) __VA_ARGS__ EMPTY()

#define CROSS1(a, b) PRINT_ROW(a, b) \
    DEFER(IF_ELSE(ISEND(a, b)) (STOP) (CROSS2)) (DEC_X0(a, b), DEC(b))

#define CROSS2(a, b) PRINT_ROW(a, b) DEFER(CROSS1) (DEC_X0(a, b), DEC(b))

#define MUL0(...) MUL1(MUL1(MUL1(MUL1(__VA_ARGS__))))
#define MUL1(...) MUL2(MUL2(MUL2(MUL2(__VA_ARGS__))))
#define MUL2(...) MUL3(MUL3(MUL3(MUL3(MUL3(__VA_ARGS__)))))
#define MUL3(...) __VA_ARGS__

#define RUN(a, b) MUL0(CROSS1(a, b))

RUN(9, 9)

ТЭЖЭ с Некрасова

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

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

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

Найденный бутылёк. Рядом реклама тройного одеколона ТЭЖЭ из газеты «Правда», №32, 2 февраля 1938 г

Бренд «ТЭЖЭ» мне раньше не попадался, хотя, как оказалось, в своё время он был очень известен и распространён, а значит и флаконов от него должно было остаться немало. Название похоже на французское, но на самом деле это аббревиатура Треста эфирно-жировых эссенций, хотя это не точно. В интернете встречаются и другие версии, но ни одна из них в аббревиатуру не укладывается.

Я поискал похожие бутыльки на интернет-аукционах, судя по всему в моём был тройной одеколон. Тройными они назывались из-за того, что в их составе были масла трёх ароматов.

Страница справочника «Вся Москва : адресная и справочная книга», Москва: товарищество А. С. Суворина «Новое время», 1930 год

«ТЭЖЭ» был огромным трестом, объединяющим в себе целый список фабрик. В 1928 году на него работали более 7000 рабочих. Трест имел следующие основные производства: парфюмерно-косметическое, мыловаренное, свечное, клееваренное, желатиновое и аппретурное, где обрабатывали текстильные материалы специальным составом — аппетром, чтобы придать им жёсткости и несминамости.

С датировкой бутылька всё сложно — трест был создан в 1922 году, а товары с этим брендом выходили вплоть до 1956 года, слишком большой диапазон. С другой стороны, все рекламные объявления этого одеколона, которые я нашёл, датируются 1930-ми. Так что можно предположить, что моя находка этого времени.

Мороз и собачий язык

Собаки, как и многие другие животные, метят территорию и читают метки других собак. Но, думаю, те, у кого собак нет, не знают, что иногда собаки лижут старые метки, чтобы на них появился запах.

У нас уже заморозки и вчера я с тревогой наблюдал (не успел вмешаться), как мой пёс лижет железку на морозе, чтобы прочитать чей-то запах. Обошлось. А то у меня как-то и плана никакого нет. Что вообще делать, если у собаки на морозе прилипнет язык к железке?

Фигня мелкая

Не могу не поделиться. На этой иллюстрации — две бабочки из рода Fignya. В роду их шесть, но я картинку обрезал, так как интереснее всего та, что слева.

Её научное название «Fignya melkaya» (то есть, натурально, «фигня мелкая»). Это название ей дали в 2009-м году сотрудник Ульяновского педагогического университета Алексей Соловьёв и основатель мюнхенского энтомологического музея Томас Витт.

Есть подозрение, что за названием всё-таки больше стоит Соловьёв. Интересно как он объяснил своему немецкому коллеге свой выбор?

Casio WQV-3

К заметке, где я писал про камеру для «Флиппера», один из читателей прислал ссылку на часы «Casio WQV-1» начала 2000-х. Интересны они тем, что у них тоже есть камера, позволяющая делать чёрно-белые снимки в оттенках серого с разрешением 120×120.

Разумеется я загорелся их купить.

На «Ебее» их можно найти без проблем, но с пересылкой часов через границу сейчас большие проблемы. Без особой надежды я пошерстил «Авито» и оказалось, что, хотя первой модели часов там нет, зато лежит третья, которую я тут же себе купил и ношу уже несколько дней.

Оцените какой ретро-футуристичный дизайн! Как будто из второй части трилогии «Назад в будущее».

Всего в линейке таких часов было четыре модели с номерами «1», «2», «3» и, почему-то, «10». Третья модель, которую я и купил, отличается от первой внешним видом и другой камерой — цветной с разрешением 176×144. Правда экранчик цвет не показывает, да и снимок умещается не весь — при просмотре видно только центральную часть.

Конечно снимки хочется из часов как-то выковырять. Проблема в том, что с часами мне не досталось ни софта, ни касиовского инфракрасного адаптера, который найти — та ещё эпопея.

Под рукой, из того, что поддерживает инфракрасный обмен, у меня только «Флиппер». В принципе, если знать протокол, можно под него написать программу, которая списывала бы снимки на карточку, оттуда перекинуть на ноутбук — ноль проблем.

Описание протокола найти было нетрудно. Но позже оказалось, что в третьей модели «Касио» перешли на некий стандартный протокол передачи, а его описание я ещё даже не искал. Возможно, раз протокол стандартный, снимки можно получить как-то проще, посмотрим. Если нет, то придётся писать программу под «Флиппер».

Я немного посмотрел АПИ для работы с инфракрасником во «Флиппере» и, пока не забыл узнанное, сделаю заметки для себя.

Для передачи сигналов подойдёт одна из двух функций. Если повезёт это будет infrared_send, которая принимает команды в одном из стандартных кодеков, либо infrared_send_raw_ext, где придётся возиться с ручным кодированием битов.

Зависит от того, что за кодировка сигналов используется в этом самом «стандартном протоколе». Если это что-то из того, что умеет «Флиппер», дело упрощается, иначе надо будет выяснять тайминги, скорость передачи и прочие технические подробности.

Наименее очевидными были для меня тайминги. Я как-то не задумывался никогда как именно кодируются «нули» и «единицы» в передачах через инфракрасный порт. Оказывается «ноль» и «единица» имеют просто разные тайминги, то есть разное время на которое загорается светодиод.

Шахматы у дочки

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

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

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

Почитал обзоры, выбрал один из популярных детских порталов — ChessKid. Пока дочка сыграла всего несколько партий с ботами и выяснила, что она по уровню между пингвином и тигром. Хочу подбить её поиграть с живыми людьми, но пока времени нет — каникулы кончились, начались домашние задания и прочая движуха.

Бумажка с Некрасова

На чердаках старинных домов довольно часто попадаются обрывки каких-нибудь старинных бумаг. Чаще всего это какие-нибудь невразумительные кусочки, где и текст-то частенько трудно прочитать, но бывают и исключения — у меня лежат несколько старых газет и книг в приличном состоянии.

Чердак на Некрасова бумагами в хорошей сохранности не порадовал. Там я нашёл несколько страниц какой-то неинтересной книги и кое-какую рванину. Единственное, что меня заинтересовало — клочок бумаги 1880-х годов из рыбнорядской гостиницы или «номеров», как это тогда называлось.

Здание тех номеров находилось на площади Габдуллы Тукая, напротив гостиницы «Татарстан». Оно было перестроено в 1872 году из бывших одноэтажных лавок купца Рязанова по проекту архитектора Петра Тихомирова. Поскольку здание находилось около Рыбнорядской площади, оно получило название Рыбнорядских номеров.

Владельцем стал купец Афанасий Музуров, кроме гостиницы в нём так же располагались ресторан, кинематограф, а так же столовая и колбасная. В разные времена в номерах проживали выдающиеся личности, в том числе будущий нарком здравоохранения Н.А. Семашко.

После революции здание стало коммунальным, а позже здесь размещалась гостиница «Татарстан». В 1992 году здание было включено в Свод памятников республиканского значения, и к юбилею Казани планировалась его реконструкция. Однако отсутствие финансирования привело к его разрушению, и сегодня от Музуровских номеров остались лишь воспоминания и открытки.

Судя по тому, что на квитке стоит имя «Пётр Афанасьевич», бумага напечатана не ранее 6 марта 1886 года по старому стилю, — тогда умер купец Афанасий Музуров, первый владелец здания гостиницы.

Сзади моей находки перечислены какие-то блюда, но надписи плохо видны. Даже при помощи специального фонарика я смог разглядеть только осетрину за 35 копеек и пельмени за 75. Кто-то неплохо погулял — больше 26 блюд на общую сумму от 5 рублей 82 копеек, остальное не разобрать.

Чтобы понять много это или нет, можно посмотреть в интернете на уровень оплаты труда в те годы. Зарплата чернорабочего в день в Питере во вторую половину 1880-х годов составляла от 64 до 73 копеек, а столяр получал от рубля 14 копеек и выше.

Крест с Некрасова

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

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

Датировать крест вряд ли получится. Не знаю что тут могли бы увидеть специалисты, я не специалист и достаточно характерных надписей тут не вижу. Не знаю возможно ли вообще провести датировку, просто его разглядывая. Может кто-то увидит какие-нибудь зацепки, но вряд ли. В конце концов, такой крестик можно изготовить хоть сейчас.

Сохран довольно плохой, не всё можно разобрать. На одной из сторон видны надписи «ЦРЪ» («царь»), на другой, внизу — «ГА» («голова Адама»). Как и надписи, почти все остальные символы тоже вполне стандартные — крест, копьё, трость, пирамида с глазом.

Единственное, не опознал символ в центре крестика на картинке слева. Можно кто-нибудь подскажет, что это такое? Думаю это вифлеемская звезда, но не уверен.

Семь минут

Одна моя знакомая называла время в семь минут «временем лжецов». Надо упомянуть, что это было ещё до навигаторов, такой точности неоткуда было взяться.

Объясняла она это так: если человек говорит, что он будет через семь минут, то он скорее всего врёт — десять минут он сказать не может, потому что это уже следующий порядок, долго, пять тоже — так как через пять он точно не будет, поэтому берёт посерёдке — семь.

Навигаторы уже давно с нами, но это правило работает до сих пор. Если человек обещает быть через семь минут, я раньше чем через минут пятнадцать—двадцать его не жду.

«ГигаЧат» и распознавание картинок

Прислали тут новость по сберовской нейросети «ГигаЧат», — теперь она научилась описывать словами изображение. Вообще не удивили, конечно. Нейросети, умеющие такое, существуют лет десять. Но, может, тут какое-то новое качество? Решил особо не миндальничать, загрузить туда какие-нибудь сложные изображения. Например, иллюстрации из заметки про кольцевую горелку от керосинки.

«ГигаЧат» ожидаемо не справился. Я готов согласиться, что горелка керосиновой лампы чем-то напоминает самовар, возможно невнимательный человек мог бы ответить так же, но на таблетку то, что я держу в руке, не похоже никак.

Интересно, что «ГигаЧат» время от времени даёт очень разные описания. Последнюю фотографию я загрузил несколько раз. Один раз он увидел вместо «таблетки» пулю, в другой раз ответил правильно — сказал, что видит «металлическую деталь круглой формы с отверстиями». Как-то сильно его мотает по смыслам.

Ещё смешнее получилось с фотографией дочки, снятой на «Флиппер» из предыдущего поста:

Для интереса и я это изображение попробовал загрузить несколько раз, получил совершенно разные, но одинаково далёкие от реальности результаты.

Я подумал, что можно написать такую же «нейросеть», которая будет в ответ на загруженную картинку генерировать какой-нибудь случайный связный текст цепями Маркова, например.

Но, справедливости ради, более понятные изображения «ГигаЧат» описывает очень неплохо. Вот пример из заметки про «метроном» в китайских боевиках:

Ещё фотки камерой «Флиппера»

Когда берёшь в руки молоток, всё вокруг становится похожим на гвозди. Раз уж я примотал камеру к «Флипперу», надо всё вокруг пофотографировать. Мы с дочкой решили сфоткать домочадцев.

Жена на работе, себя я фоткал вчера, поэтому слева направо: улитки Тайгер и Найгер, кот Марсик, пёс Бейсик и дочь Ева.

Деталь с Некрасова

В одни выходные меня пригласили поискать на чердаке одного из домов расселяемых на Некрасова что-нибудь интересное. Продолжаю рассказывать про находки.

Следующая деталь, которую я нашёл, сначала поставила меня в тупик. Думаю я долго разбирался бы что это такое, но выручила надпись — POLARSTERN BRENNER 15’’’.

Слово brenner («горелка» по-немецки) мне было знакомо — в земле постоянно находятся детали керосиновых ламп, на них иногда бывает такая надпись. Можно было догадаться, что это тоже какая-то часть керосинки, но какая — я не знал, не находил ещё таких.

Деталь от керосиновой лампы с надписью Polarstern Brenner 15‴

Разобрался только дома, когда нашёл фотографию керосиновой лампы определённого устройства. Найденная штуковина, — кольцевая горелка, в её видно наверху фотографии лампы в сборе.

Место этой детали в керосиновой лампе

Горелка сделана компанией Хьюго Шнайдера, которая располагалась в немецком городе Лейпциге. «Polarstern» («Полярная звезда») — это модель, а число «15», в надписи, согласно каталогу 1911 года, — это размер (диаметр) горелки в линиях, которые, в данном случае, равны 1⁄10 дюйма.

История компании начинается с мастерской Эрнста Хеккеля, открытой в 1854 году в Вурцене. В 1863 году он основал мануфактуру Häckel und Schneider, которая к 1877 году значительно увеличила выручку. В 1871 году контроль над фирмой перешел к Хуго Шнайдеру, сыновья которого в 1899 году преобразовали её в акционерное общество Hugo Schneider Aktiengesellschaft (HASAG). Основным бизнесом было производство ламп.

В 1903 году компания начала производство автомобильных ламп и с началом Первой мировой войны переключилась на военное производство. С 1930-х годов HASAG стала одним из крупнейших поставщиков вооруженных сил, используя подневольный труд, в том числе узников концлагерей. После Второй мировой войны фирма продолжала производить гражданскую продукцию до 1947 года, когда её мощности были вывезены в СССР. Сохранилось лишь административное здание, ныне в этом месте находится Лейпцигский научный парк.

Фабрика горелок и ламп Хьюго Шнайдера. Из справочника «Leipzigs grossindustrie und grosshandel in ihrer kulturbedeutung», Paul Hirschfeld, 1887, страница 147

Установить время изготовления найденной мной детали затруднительно, но если покопаться в интернете, можно узнать, что патент на первую горелку такого типа был выдан 15 января 1884 года в США Леонарду Хенкле, в Германии они появились в 1895-м в виде горелки «Матадор» компании «Эрих & Граец». Позже такие горелки скопировали и другие производители, включая компанию Хьюго Шнайдера.

Камера для «Флиппера»

Около трёх месяцев назад, болтаясь по интернету, я, волею случая, наткнулся на репозиторий с софтом, позволяющим подключить к «Флипперу» небольшую веб-камеру. Для подключения внешних модулей у него на боку есть специальный разъём.

Выглядело это забавно, да и цена вопроса — всего 400 рублей, плюс комплект перемычек за 30. Невеликие траты за такую прикольную штуку. Я что-то тянул с этой покупкой, но, в конечном счёте, купил, конечно. Кстати, камеру можно было найти и дешевле, но я побоялся, что приедет какой-нибудь мусор, а тут хотя бы продавец с хороший рейтингом.

«Флиппер Зеро» с камерой в сборе

Из-за того, что нужные программы довольно долго скачивались, собрал всё вместе и поставил нужный софт примерно за час. Чистого времени ушло минут двадцать, мог бы и меньше потратить, но перепутал штырьки.

Если внимательно следовать инструкции, то всё просто: четырьмя перемычками соединяешь «Флиппер» и плату, ещё одной замыкаешь между собой два штырька — это нужно, чтобы залить в камеру прошивку. Потом скачиваешь редактор для «Ардуино», там ставишь плагин, далее через «Флиппер» с его помощью заливаешь в камеру прошивку, размыкаешь перемычку. Потом через магазин приложений ставишь нужную программу и развлекаешься.

Единственная хитрость — плагин надо ставить второй версии, а не третьей, в третьей почему-то нет поддержки нужной платы.

Экранчик у «Флиппера» маленький и чёрно-белый, поэтому изображение посредственное, но так только интереснее — качественное изображение я могу и на смартфоне увидеть, а тут настоящий олдскул!

Жизнь — боль

«Яндекс.Клавиатура» кое-что знает о жизни, но путает дефис и тире:

Пуговица с Некрасова

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

Моя третья находка — гербовая пуговица. Я очень их люблю, несмотря на однообразие — обычно находятся пуговицы одних и тех же производителей. В данном случае это пуговица произведённая на фабрике Ивана Игнатьевича Копейкина, которую он открыл вместе с братьями в Санкт-Петербурге в 1840 году. Довольно частая находка.

Пуговица Копейкина. 1 сорт, Санкт-Петербург

Позже, 1858 году из-за семейных разногласий пути братьев разошлись. Каждый открыл свой бизнес, но успеха добились только двое — у Авксентия была большая пуговичная фабрика, и в 1872 году он стал купцом 2 гильдии, у Максима была своя пуговичная мастерская.

Насколько я понял из материалов в интернете, клеймо «Копейкин» ставила только фабрика Ивана Игнатьевича, его братья дописывали ещё и инициалы или имя. Если это так, то это пуговица 1840-1850-х годов.

Интересно, что на ушке сохранились нитки, то есть когда-то пуговица была к чему-то пришита.

Ранее Ctrl + ↓