IOCCC (енгл. International Obfuscated C Code Contest) је такмичење на пољу програмирања, на коме је циљ написати што креативнији нејасан C код. Суштина је у писању неразумног и несхватљивог изворног кода са свим могућим злоупотребама правила писања у намери да се у што мање кода смести што комплекснији програм. Оснивачи такмичења су Landon Curt Noll и Larry Bassel, а такмичење се од године 1984. одржава редовно, са изузетком година 1997, 1999, 2002, 2003. Идеја потиче од веома нејасног кода који су ова два програмера у то време одржавали. Одлучили су да направе такмичење за најгори могући C код, и заиста: у оквиру ограничења од неколико килобајта, такмичари остварују разне ствари - победнички код на такмичењу 2004. године је постао оперативни систем.
Бројни примери се могу видети на IOCCC сајту.
Да би нам помогли око ширине посла, молимо вас да пратите следећа правила:
Сваки OCC програм може бити објашњен његовом формалном анализом. Најчешће је потребно изразити га замењивањем нејасних делова кода еквивалентним али јаснијим.
Овде ће бити објашњен један програм који штампа карту Индије.
#include<stdio.h> main() { int a,b,c; for (b=c=10;a= "- LLLLLL?, LMKC,XYZHELLO FOLKS,\ TFy!QJu ROo TNn(ROo)SLq SLq ULo+\ UHs UJq TNn*RPn/QPbEWS_JSWQAIJO^\ NBELPeHBFHT}TnALVlBLOFAkHFOuFETp\ HCStHAUFAgcEAelclcn^r^r\\tZvYxXy\ T|S~Pn SPm SOn TNn ULo0ULo#ULo-W\ Hq!WFs XDt!" [b+++21];) for(; a-- > 64 ; ) putchar ( ++c=='Z' ? c = c/ 9:33^b&1); }
Овај програм се да написати и овако. Понашање је еквивалентно.
#include <stdio.h> const char *p = " TFy!QJu ROo TNn(\ ROo)SLq SLq ULo+UHs UJq TNn*RPn/QPbEWS_JSWQAIJO^NBELPeHBFHT}TnAL\ VlBLOFAkHFOuFETpHCStHAUFAgcEAelclcn^r^r\\tZvYxXyT|S~Pn SPm SOn T\ Nn ULo0ULo#ULo-WHq!WFs XDt!"; main() { int a, // одређује када се итерације прекидају b, // одређује да ли ће бити штампани узвичници или размаци c; // одређује када се прелази у следећу линију for(b=c=10;a=p[b+21];) // пролази са офсетом кроз стринг { b++; while( a > 64 ) // штампање низа узвичника или размака { a--; c++; if(c==90) // замена за c=='Z', време је за нови ред { c = 10; putchar('\n'); } else { if(b%2) putchar(' '); // (не)парност b одлучује шта ће бити штампано else putchar('!'); } } } return 0; }
Коментари у коду већ говоре понешто. Прва ствар која се да приметити јесте да првих 31 симбола стринга неће бити употребљени у програму, те се на њиховом месту сме оставити било шта. Конкретно овде су стављени знаци размака. Од 32. симбола па надаље почиње се са читањем симбола редом помоћу вредности b+21. Тај део стринга је у ствари компримована карта која одређује колико и када ће којих симбола бити исписано, у секвенци. На пример када се променљивој a додели прво слово коришћеног дела низа, T, иста ће бити декрементирана до вредности 64 (или ће се прећи на следећу, уколико је у старту мања од 65) и за то време ће бити штампано 'T'-64 = 84 - 64 = 20 симбола. Зависно од парности b ови симболи могу бити узвичници (непарно) или размаци (парно). Значи на почетку излаза би се требало наћи 20 размака као што и јесте случај. Следи 'F' 'F'-64 = 70-64 = 6, што уз инкрементирање b значи да следи шест узвичника итд.
Променљива c одређује када ће бити штампан знак за нову линију. У почетку је она 10, а увећава се за један приликом штампања сваког знака узвика или размака, док се нова линија штампа сваки пут када иста достигне вредност 90 (ASCII код за 'Z'). Након штампања знака за нову линију вредност c бива враћена на 10 и тако даље.
Када се дође до краја стринга, променљива a ће у услову for петље добити вредност нула што значи завршавање ове петље, а са њом и програма.