由于从问题中删除了原始代码并重新格式化了一个被替换的代码,因此我从主题启动器给出的代码开始。
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);}
从恢复结构开始。在它们所属的位置添加空格和换行符。请记住,Cint
在未指定时假定数据类型。
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 语言中:
- 没有“字符”类型。一个字母只是一个(通常是 8 位)整数。因此
'-' - '-'
是 0 和'/' / '/'
1(就像i/i
后面一样)
- 没有“字符串”类型——这只是一个指向“字符”的指针
- 根据定义,数组和指针是同一个东西
- 无大小(字节大小)的指针和整数相互隐式转换。
注意:在下面的评论中,人们认为在 C 数组中不是指针,而只是隐式类型转换为指针。这在理论上可能是正确的,但似乎对这段特定代码没有任何实际意义。但是,项目符号 3 可能被书本错误地表述了。
还让我们假设所有全局变量都是零初始化的。
因此i["]<i;++i){--i;}"]
是 0[指向某个字符串的指针],然后是 1[指向某个字符串的指针],等等。实际上是字符串的第 i 个字符。
它用于第二个参数位置的 for 循环 - 条件检查器。所以实际上这可以重新表述为
for( ; "]<i;++i){--i;}"[i] != '\0'; read... );
或通过 C for 循环的定义
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 标准,预定义了以下文本文件:
- 0 - STDIN - 从键盘读取
- 1 - STDOUT - 打印到显示器/打印机/日志文件/等
- 2 - STDERR - 关于错误情况的紧急打印
因此:
/* 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);
}
}
你能弄清楚这个片段现在是如何工作的吗?;-)
只需添加空格和新行 - 正确的代码结构格式 - 它变得容易小便:-)