Отличный способ запомнить новое — связать его с чем-то, что вы уже знаете, так что теперь эта статья окажет на вас двойной эффект: она заставит вас спеть и запомнить этот анализ того, как человек по имени Джим Хейг выиграл IOCCC ( International Obfuscated C Code Contest) в 1989 году с тем, что казалось предвестником хита 1999 года «I’m blue» группы Eifel 65.
Давайте посмотрим на выигрышный код Джима:
Если вы бросите быстрый взгляд на это, вы, скорее всего, заметите две вещи: во-первых, в этом коде есть несколько макросов, определенных в заголовке, которые сообщают вам, какие слова представляют какие символы, а затем идет прекрасно запутывающий код, созданный Джимом Хейгом.
Помня об этих двух вещах, можно начать расшифровывать возможные замены в теле текста и некоторые намеки на то, что они могут сделать. В этом случае гораздо быстрее скомпилировать эту программу с флагом gcc -E. Флаг -E покажет вам предварительно скомпилированный текст, чтобы макросы в заголовке читались, а затем использовались для замены соответствующих блоков содержимого в теле. Вот результат, который вы получите после этого процесса:
# 1 "hague.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 1 "<command-line>" 2 # 1 "hague.c" # 10 "hague.c" char _DAH_[]="ETIANMSURWDKGOHVFaLaPJBXCYZQb54a3d2f16g7c8a90l?e'b.s;i,d:"; main ( ) { char *_DIT, *DAH_, *DIT_, *_DIT_ , *malloc(),* gets ( ); for(_DIT=malloc( 81 ), DIT_=_DIT++; _DIT == gets( _DIT ); __DIT('\n') ) for ( DAH_=_DIT; *DAH_;__DIT ( *_DIT_?_DAH ( * DIT_ ):'?'),__DIT(' '), DAH_++ ) for (*DIT_ = 2, _DIT_ = _DAH_;*_DIT_ && ( *_DIT_ != ( *DAH_ >= 'a' ? *DAH_ &223 : *DAH_));(*DIT_)++,_DIT_++)*DIT_+=( * _DIT_>='a'? * _DIT_-'a':0);} _DAH( DIT_ ) { __DIT ( DIT_ > 3 ? _DAH ( DIT_>>1 ): '\0' ); return DIT_&1 ? '-' : '.'; } __DIT( DIT_ ) char DIT_; { ( void ) write ( 1,&DIT_,1 ); }
Показанный выше код — это результат, который вы получите, если проведете код Джима через стадию предварительной компиляции. Теперь вы можете более четко видеть, о чем идет речь и как устроен код, даже если он все еще не на 100% понятен с первого взгляда (что является целью).
Можно получить панорамное представление о том, что делает этот код, внимательно изучив структуру.
Вы заметите макросы заголовка вверху:
Массив символов с именем _DAH_ :
ГЛАВНАЯ функция:
Функция _DAH(DIT_):
Функция __DIT(DIT_):
Это немного помогает, не так ли?
Продолжим разгадывать тайну и теперь полностью скомпилируем программу. На этот раз мы не будем использовать флаги для определения конкретного этапа процесса компиляции, а вместо этого просто назовем результат «ПУТАНИЦА» для катарсиса. Результат весьма приятен, и здесь я покажу вам:
- Скомпилировать.
- Выполнять.
- Подождите, пока что-то произойдет.
- Введите случайный текст и нажмите Enter.
- Выгода.
Джим Хейг, по сути, создал очень запутанную программу, которая создает запутанный способ общения. Его остроумие было ясно продемонстрировано в этой программе и признано IOCCC увековеченным в умах будущих поколений программистов.
Цель этого конкурса — продемонстрировать, насколько неприятным может быть код программиста и почему важно придерживаться передового опыта в кодировании (еще и потому, что это весело).
Теперь, когда тайна кода Джима разгадана, вопрос все еще остается без ответа: вы?