もっとも便利な難読化
xxxxxxxxxx
#include <stdio.h>
#define O1O printf
#define OlO putchar
#define O10 exit
#define Ol0 strlen
#define QLQ fopen
#define OlQ fgetc
#define O1Q abs
#define QO0 for
typedef char lOL;
lOL*QI[] = {"Use:\012\011dump file\012","Unable to open file '\x25s'\012",
"\012"," ",""};
main(I,Il)
lOL*Il[];
{ FILE *L;
unsigned lO;
int Q,OL[' '^'0'],llO = EOF,
O=1,l=0,lll=O+O+O+l,OQ=056;
lOL*llL="%2x ";
(I != 1<<1&&(O1O(QI[0]),O10(1011-1010))),
((L = QLQ(Il[O],"r"))==0&&(O1O(QI[O],Il[O]),O10(O)));
lO = I-(O<<l<<O);
while (L-l,1)
{ QO0(Q = 0L;((Q &~(0x10-O))== l);
OL[Q++] = OlQ(L));
if (OL[0]==llO) break;
O1O("\0454x: ",lO);
if (I == (1<<1))
{ QO0(Q=Ol0(QI[O<<O<<1]);Q<Ol0(QI[0]);
Q++)O1O((OL[Q]!=llO)?llL:QI[lll],OL[Q]);/*"
O10(QI[1O])*/
O1O(QI[lll]);{}
}
QO0 (Q=0L;Q<1<<1<<1<<1<<1;Q+=Q<0100)
{ (OL[Q]!=llO)? /* 0010 10lOQ 000LQL */
((D(OL[Q])==0&&(*(OL+O1Q(Q-l))=OQ)),
OlO(OL[Q])):
OlO(1<<(1<<1<<1)<<1);
}
O1O(QI[01^10^9]);
lO+=Q+0+l;}
}
D(l) { return l>=' '&&l<='\~';
}
引用元:https://www.ioccc.org/1986/bright/bright.c
審査員・作者による説明:https://www.ioccc.org/1986/bright/hint.html
ファイルの16進ダンプ。
$ gcc -o bright bright.c
$ ./bright hello.txt
0: 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 20 49 4f Hello, world! IO
10: 43 43 43 a CCC.
バイナリの0と1にちなんで、識別子はOQ0
とIlL1
で構成されているものがほとんど。
演算子もビット演算関係のものが無駄に多い。
単に読みにくくするのではなく、難読化のネタがプログラムの挙動にちなんだものになっている最初期の例。
現代のgccではcond && exit(1)
がerror: void value not ignored as it ought to be
になるので、cond && (exit(1), 0)
などと変更する必要があった。
xxxxxxxxxx
--- bright.c
+++ bright.c
O=1,l=0,lll=O+O+O+l,OQ=056;
lOL*llL="%2x ";
- (I != 1<<1&&(O1O(QI[0]),O10(1011-1010))),
- ((L = QLQ(Il[O],"r"))==0&&(O1O(QI[O],Il[O]),O10(O)));
+ (I != 1<<1&&(O1O(QI[0]),O10(1011-1010),0)),
+ ((L = QLQ(Il[O],"r"))==0&&(O1O(QI[O],Il[O]),O10(O),0));
lO = I-(O<<l<<O);
while (L-l,1)
{ QO0(Q = 0L;((Q &~(0x10-O))== l);