avva: (Default)
avva ([personal profile] avva) wrote2002-08-08 04:06 pm

загадка (для программистов)

Загадка: что напечатает приведенная ниже однострочная программа, если её запустить? Желательно отгадать, не запуская. Если никак не получится, советую хотя бы попробовать объяснить, почему она печатает то, что печатает. Кстати, компилировать и запускать надо на каком-нибудь Юниксе (почему? дополнительный вопрос).

main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}

Это одна из самых любимых мной программ из числа победителей Obfuscated C Contest. Она победила в категории one-liner в 87-м году. А ещё одна программа-победительница в том же году замечательно иллюстрирует тезис статьи Дейкстры "Goto statement considered harmful":
#include <stdio.h>
#include <malloc.h>
main(togo,toog)
int togo;
char *toog[];
{char *ogto,   tgoo[80];FILE  *ogot;  int    oogt=0, ootg,  otog=79,
ottg=1;if (    togo==  ottg)   goto   gogo;  goto    goog;  ggot:
if (   fgets(  tgoo,   otog,   ogot)) goto   gtgo;   goto   gott;
gtot:  exit(); ogtg: ++oogt;   goto   ogoo;  togg:   if (   ootg > 0)
goto   oggt;   goto    ggot;   ogog:  if (  !ogot)   goto   gogo;
goto   ggto;   gtto:   printf( "%d    goto   \'s\n", oogt); goto
gtot;  oggt:   if (   !memcmp( ogto, "goto", 4))     goto   otgg;
goto   gooo;   gogo:   exit(   ottg); tggo:  ootg=   strlen(tgoo);
goto   tgog;   oogo: --ootg;   goto   togg;  gooo: ++ogto;  goto
oogo;  gott:   fclose( ogot);  goto   gtto;  otgg:   ogto=  ogto +3;
goto   ogtg;   tgog:   ootg-=4;goto   togg;  gtgo:   ogto=  tgoo;
goto   tggo;   ogoo:   ootg-=3;goto   gooo;  goog:   ogot=  fopen(
toog[  ottg],  "r");   goto    ogog;  ggto:  ogto=   tgoo;  goto
ggot;}

[identity profile] ex-ilyavinar899.livejournal.com 2002-08-08 06:14 am (UTC)(link)
Если там определено #ifdef unix 1, то

main() { printf(&1["\021%six\012\0"],(1)["have"]+"fun"-0x60);}

main() { printf("%six\012\0",'а'+"fun"-0x60);}

main() { printf("%six\012\0",0х61+"fun"-0x60);}

main() { printf("%six\012\0","un");}

main() { printf("unix\n\0"); }

unix

Re:

[identity profile] avva.livejournal.com 2002-08-08 06:20 am (UTC)(link)
Ты знал! Ты знал! ;)
Я пока скрою твой коммент, чтобы дать ещё другим возможность порешать.

[identity profile] hotgiraffe.livejournal.com 2002-08-08 06:25 am (UTC)(link)
Кстати, очень забавные вещи происходят, когда пишешь коммент на коммент, а того в это время скринят.

А вопрос, собственно, был такой - говорит ли ANSI C, что charset - всегда ASCII (в младшей половине) ?
Ибо с EBCDIC, например, этот номер не пройдёт - константу править придёцца.

Re:

[identity profile] avva.livejournal.com 2002-08-08 06:29 am (UTC)(link)
Не помню, говорит или нет.
Но никто не сказал, что она обязана быть 100% ANSI C compliant.

[identity profile] cema.livejournal.com 2002-08-08 07:30 am (UTC)(link)
говорит ли ANSI C, что charset - всегда ASCII (в младшей половине) ?

Видимо, нет, хотя есть устойчивое мнение, что да. Подробности тут.

Однако же

(Anonymous) 2002-08-08 06:16 am (UTC)(link)
Однако же, было бы чертовски любопытно узнать, что же делает хотя бы вторая из программ. (Надеюсь, впрочем, дождаться и первой "отгадки")

    Лошадь

[identity profile] hotgiraffe.livejournal.com 2002-08-08 06:19 am (UTC)(link)
Ой-ой, #include-ы поправьте пожалуйста во второй ;)

[identity profile] avva.livejournal.com 2002-08-08 06:21 am (UTC)(link)
Упс ;)

[identity profile] anton.livejournal.com 2002-08-08 06:28 am (UTC)(link)
Это просто на самом деле, только запутано.
"unix" ;)

Re:

[identity profile] avva.livejournal.com 2002-08-08 06:30 am (UTC)(link)
Хорошо, а вторая программа? ;)

[identity profile] anton.livejournal.com 2002-08-08 07:05 am (UTC)(link)
Брр...
Вторая считает количество goto в файле ;)

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

[identity profile] anton.livejournal.com 2002-08-08 07:12 am (UTC)(link)
Распутывание её, правда, тупая задачка, так что не за что!

Спасибо Вам за неё! Буду её приводить как довод против goto абитуриентам, которых С учу. Выглядит уж очень здорово!

[identity profile] sobaker.livejournal.com 2002-08-08 06:30 am (UTC)(link)
unix - макрос. Равен 1.

Здесь используется "обратный" синтаксис обращения к массиву (т.е. s[3] == 3[s])

&unix["\021%six\012\0"] дает адрес символа в массиве, следующего за первым (так мы пропускаем красивый \021).

\012 - это \n в восемеричной записи. Т.е. формат-строка имеет вид "%s ix\n" (пробел вставил для наглядности).

Аргумент printf'а: адрес строки "fun", к которому прибавлено число 'a'-0x60 ('a' получили из (1)["have"]). Очевидно, что 'a'-0x60 = 97-96 = 1. Т.е. не "fun", "un".

Итого: printf("%six\n", "un"). Иначе говоря - "unix".

Получил удовольствие :)

Re:

[identity profile] avva.livejournal.com 2002-08-08 06:31 am (UTC)(link)
Всё правильно, здорово ;) раскрываю первый коммент [livejournal.com profile] ilyavinarsky, к-й тоже правильно решил.

зачем это, a?

[identity profile] zc2.livejournal.com 2002-08-09 10:34 am (UTC)(link)
Интересно, в каких случаях практически может пригодиться обратная нотация доступа к массиву? Или только для постановки подобными задачками в тупик начинающих программистов?.. ;-)

Re: зачем это, a?

[identity profile] avva.livejournal.com 2002-08-11 02:14 am (UTC)(link)
Практически не может пригодиться, но педагогический смысл в ней есть. Настоящий программист на C должен понимать, что a[b] - это всего лишь синтаксический вариант *(a+b), что эти две формы абсолютно идентичны. Форма b[a] напоминает об этом.

Хм

[identity profile] barsen.livejournal.com 2002-08-08 06:46 am (UTC)(link)
Странные загадки... Ответ и на первую и вторую находится на гугле с полпинка, соответственно смысла нет их публиковать... Ну, по крайней мере, в разделе загадок.
Вот кто бы лучше ключ дал как девятый уровень пройти в веболомке, так и не допер...

Re: Хм

[identity profile] ex-innin997.livejournal.com 2002-08-08 06:52 am (UTC)(link)
в разделе загадки (http://www.livejournal.com/users/zagadki/), как вы красиво сказали, это я опубликовал ссылку на постинг [livejournal.com profile] avva так что не надо на него наезжать :)

Не не не....

[identity profile] barsen.livejournal.com 2002-08-08 07:05 am (UTC)(link)
Я не наезжал... Само по себе это разумеется интересно
Вообще, я обожаю загадки

Re: Хм

[identity profile] anton.livejournal.com 2002-08-08 07:17 am (UTC)(link)
А смысл искать ответы гуглем, если можно решить. Странное занятие получается - искать ответы на загадки, за разгадку которых ничего, кроме удовольствия от решения их получить не получится.
stas: (Default)

[personal profile] stas 2002-08-08 07:11 am (UTC)(link)
В первой для красоты эксперимента хорошо бы сделать goto.h, в котором, соотв.,
#define togt printf
#define ttgo fclose

и т.п. вплоть до ифов :)
stas: (Default)

[personal profile] stas 2002-08-08 07:11 am (UTC)(link)
во второй, тоиссь...

[identity profile] anton.livejournal.com 2002-08-08 07:14 am (UTC)(link)
Cтройность потеряется. Она сейчас выглядит хорошо.
(deleted comment)

[identity profile] cema.livejournal.com 2002-08-08 09:41 am (UTC)(link)
В этом варианте предполагается ASCII. Легко переделать на общий случай.