我在ioccc中看到了这一点。
int i;
main()
{
for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hello, world!\n",'/'/'/'));
}
read(j,i,p)
{
write(j/p+p,i---j,i/i);
}
打印出“你好世界!”使用gcc编译时,不确定它是否适用于visual studio 12。 有人可以向我解释它是如何运作的吗?
答案 0 :(得分:4)
由于原始代码已从问题中删除并重新格式化,因此我将替换为主题启动程序提供的代码。
int i;main(){for(;i["]<i;++i){--i;}"];
read('-'-'-',i+++"hello, world!\n",'/'/'/'));
}read(j,i,p){write(j/p+p,i---j,i/i);}
从恢复结构开始。添加它们所属的空格和换行符。请记住,未指定时,C假定int
数据类型。
int i;
/* int */ main()
{
for( ; i["]<i;++i){--i;}"];
read( '-' - '-',
i++ + "hello, world!\n",
'/' / '/') );
}
/* int */ read( /* int */ j,i,p)
{
write( j/p + p, i-- - j, i/i );
}
注意用C语言:
'-' - '-'
为零且'/' / '/'
为1(后面就像i/i
一样)注意:在下面的评论中,人们认为在C数组中不是指针,而是隐含地指向指针。这在理论上可能是正确的,但似乎对这个特定代码没有任何实际意义。但是,一本子弹3可能也被书籍错误地制定了。
另外,让我们假设所有全局变量都是零初始化的。
因此i["]<i;++i){--i;}"]
为0 [指向某个字符串的指针],然后是1 [指向某个字符串的指针],等等。实际上是字符串的第i个字符。
它用于第二个参数位置的for循环 - 条件检查器。所以实际上这可以重新制定为
for( ; "]<i;++i){--i;}"[i] != '\0'; read... );
或根据C for loop的定义
while ( "]<i;++i){--i;}"[i] != 0 ) { read ...; }
两条线都有14个字符,这不是一个证据:
"hello, world!\n"
"]<i;++i){--i;}"
这使得它只是字符串中每个字符的循环,您可以将其重新表示为
for i := 0 to 14-1 do
将这一切粘在一起,程序变成
int i;
/* int */ main()
{
for( i=0; i<strlen("hello, world!\n"); i++)
{
read( 0, & "hello, world!\n"[i], 1);
}
}
有点容易吗?现在转移到函数本身...和C文件句柄。根据UNIX标准,预定义了以下文本文件:
因此:
/* int */ read( j = 0, i = pointer-to-letter-to-print, p = 1)
{
write( j/p + p, // 0/1 + 1 == 1 == STDOUT
i-- - j, // == i itself due to j == 0;
// -- is POST-decrement and does not affect the calculation
i/i /*== 1 as long as i != 0 - meaning print only single character*/ );
}
再次粘合在一起:
int i;
int my_read( int j, char * pChar, int p)
{
write( STDOUT, pChar, 1 );
pChar--; // does not affect anything, as mentioned above
}
const char msg[] = "hello, world!\n";
int main(void)
{
for( i=0; i<strlen(msg); i++)
{
my_read( 0, &msg[i], 1);
}
}
你能弄清楚这个片段现在如何运作吗? ; - )
只需添加空格和新行 - 正确的代码结构格式化 - 它变得容易 - 俗气: - )
答案 1 :(得分:1)
'-'-'-'
的结果是 0 。 '/'/'/'的结果是 1 。
所以,read('-'-'-',i+++"hello, world!\n",'/'/'/'));
实际上是
read(0,i+++"hello, world!\n",1));
关于循环:for(;i["]<i;++i){--i;}"];
i["]<i;++i){--i;}"]
实际上是
"]<i;++i){--i;}"[i]
因为在C中,如果你写a[i]
,它相当于i[a]
(*(a+i) == *(i+a)
)
所以这个for循环将继续前进,直到遇到最后一个字符。
总而言之,理解这里发生的事情很容易。 (我在此链接中找到了更多解释:http://www.cs.washington.edu/education/courses/cse142/97su/josh/obfuscate.html)
答案 2 :(得分:0)
让我们首先更好地格式化这个:
int i;
main()
{
for(;i["]<i;++i){--i;}"];
read('-'-'-',i++ + "hello, world!\n",'/'/'/'));
}
read(j,i,p)
{
write(j/p+p,i---j,i/i);
}
其次,我们看看它实际上做了什么:
for(;i["]<i;++i){--i;}"];
与
相同for(;"]<i;++i){--i;}"[i];
因此,没有初始化,并且只要i
索引的“C代码”的字符串不为零。
然后是for循环的更新部分:
read('-'-'-',i++ + "hello, world!\n",'/'/'/'));
'-'-'-'
就像'a'-'a'
一样为零。 i++ + "hello, world!"
是指针+偏移量,当然更新“i”。最后一部分是自己划分的东西,这就是1.
最后一招是重新定义的read
函数,它调用write:
read(j,i,p)
{
write(j/p+p,i---j,i/i);
}
它使用类似的技巧来生成stdout
的值,其中j / p + p(从上面p = 1,j = 0,所以0/1 + 1 = 1)和数据的长度写(1)。要写的字符是i-- -j
,因为我们在执行i
之前采用--
,它没有效果[它不是使用全局i
,而是使用read
本地的{{1}} {1}}。