我是 C 新手,我急切地想知道这段代码有何魔力?
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
来源可以在这里找到:http://www.ioccc.org/1984/anonymous.c
以下是代码附带的提示:
不光彩的提及: 匿名
作者太丢人了,能写出这么垃圾的东西,所以 我答应保护他们的身份。我要说的是作者 该程序与 C 编程有众所周知的联系 语言。这个节目是古老的“你好, world”程序。读起来像读,写起来也像写! 版权所有 (c) 1984,兰登·科特·诺尔。版权所有。允许 允许用于个人、教育或非营利用途,前提是 本版权和声明完整包含并保留 不变。所有其他用途必须事先获得书面许可 来自兰登·科特·诺尔和拉里·巴塞尔。
当您有混淆的代码时,您需要清理物理布局,添加一些空白,添加必要的缩进,然后编译代码。来自编译器的警告会告诉您很多有关程序隐藏的一些内容。
首次简化 - 添加空白
int i;
main()
{
for( ; i["]<i;++i){--i;}"];
read('-'-'-', i+++"hell\o, world!\n", '/'/'/'));
}
read(j,i,p)
{
write(j/p+p,i---j,i/i);
}
当使用
gcc -Wall
编译程序时,我收到以下警告:
soc.c:2:1: warning: return type defaults to ‘int’ [enabled by default]
main()
^
soc.c: In function ‘main’:
soc.c:4:4: warning: implicit declaration of function ‘read’ [-Wimplicit-function-declaration]
for( ; i["]<i;++i){--i;}"]; read('-'-'-', i+++"hell\o, world!\n", '/'/'/'));
^
soc.c:4:50: warning: unknown escape sequence: '\o' [enabled by default]
for( ; i["]<i;++i){--i;}"]; read('-'-'-', i+++"hell\o, world!\n", '/'/'/'));
^
soc.c: At top level:
soc.c:7:1: warning: return type defaults to ‘int’ [enabled by default]
read(j,i,p)
^
soc.c: In function ‘read’:
soc.c:7:1: warning: type of ‘j’ defaults to ‘int’ [enabled by default]
soc.c:7:1: warning: type of ‘i’ defaults to ‘int’ [enabled by default]
soc.c:7:1: warning: type of ‘p’ defaults to ‘int’ [enabled by default]
soc.c:9:4: warning: implicit declaration of function ‘write’ [-Wimplicit-function-declaration]
write(j/p+p,i---j,i/i);
^
soc.c:9:17: warning: operation on ‘i’ may be undefined [-Wsequence-point]
write(j/p+p,i---j,i/i);
^
soc.c:9:17: warning: operation on ‘i’ may be undefined [-Wsequence-point]
soc.c:10:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
二次简化 - 去混淆
基于上述警告,程序可以被反混淆为:
int i;
void read(int j, char* i, int p);
void write(int j, char* i, int p);
int main()
{
for( ; i["]<i;++i){--i;}"];
read('-'-'-', i+++"hell\o, world!\n", '/'/'/'));
return 0;
}
void read(int j, char* i, int p)
{
write(j/p+p, (i--) - j, 1);
}
上述版本没有编译器警告并产生相同的输出。
第三次简化 - 进一步消除混淆
表达式
i["]<i;++i){--i;}"]
用于运行循环 14 次。就那么简单。可以简化为i < 14
。
'-'-'-'
与 '-' - '-'
相同,等于 0
。
'/'/'/'
与 '/' / '/'
相同,等于 1
。
i+++"hello, world!\n"
与 i++ + "hello, world!\n"
相同,与 s + i++
相同,其中 s
可以是 char const* s = "hello, world!\n";
for
循环可以简化为:
char const* s = "hello, world!\n";
for( ; i < 14; read(0, s+i++, 1));
由于
j
中read
的值始终为零,因此read
的实现可以简化为:
void read(int j, char* i, int p)
{
write(0, (i--), 1);
}
表达式
(i--)
可以简化为 i
,因为递减作为副作用不会改变函数的工作原理。换句话说,上面的函数就是:
void read(int j, char* i, int p)
{
write(0, i, 1);
}
当我们意识到参数
j
的值始终为0
并且参数p
的值始终为1
时,我们可以将主函数中的for
循环更改为:
for( ; i < 14; i++)
{
write(0, s+i, 1);
}
因此,整个程序可以简化为:
void write(int j, char const* i, int p);
int main()
{
int i = 0;
char const* s = "hello, world!\n";
for( ; i < 14; i++ )
{
write(0, s+i, 1);
}
return 0;
}
第四次简化 - 让它变得微不足道
以上版本有硬编码编号
14
。这就是 s
中的字符数。因此,该程序可以通过将其更改为变得简单:
void write(int j, char const* i, int p);
int main()
{
write(0, "hello, world!\n", 14);
return 0;
}
让我们重写一下代码,替换一些表达式并添加注释
int i; // i = 0 by default
main()
{
for( ;
"]<i;++i){--i;}" [i]; // magic: it is the same as i["]<i;++i){--i;}"];
// the important part is that there's 14 chars in the
// string, same length that "hello, world!\n"
// the content of the string has no importance here,
// in the end 'i' will go from 0 to 14
read(0, // since '-' - '-' is equal to 0,
"hello, world!\n" + (i++), // same as i+++"hello, world!\n"
// it is pointers arythmetic
// the second arg to the read
// function defined further points
// to the letter to print
1)) // '/' / '/' division result is 1
;
}
// the read function is then always called with
// j == 0
// i is a pointer to the char to print
// p == 1
// And for the obfuscation fun, the read function will write something :)
read(j,i,p)
{
write(0, // j/p+p is equal to 0, which is the stdout
i, // i-- - j is equal to i, decrement of i comes later
1); // i / i is equal to 1, this means one char to print
}