虽然这段代码不符合标准,但gcc会编译它,输出与我对代码的分析一致。可悲的是,如果没有更多上下文,我无法真正解释输出。如果我忽略退格,输出看起来像这样:
C!o!r!s!i!...
为了分析代码,我们将首先对其进行一些格式化:
#include <stdio.h>
char* _ ="XxTIHRCXCxTIHRXRCxTIHXHRCxTIXIHRCxTXTIHRCxXxTIHRCX";
int main(int l){
for(l+=7; l != putchar(010); ++l); // 010 = 8 -> backspace char
if(*(++_))
main(
*_ != 88 ? // *_ != 'X'
( putchar(*_ ^ 073) | putchar(33) ) & 1 : // 33 = '!'
0xffff2a8b);
}
在我们继续之前,有几点值得注意:
- 如果putchar 成功,则返回它传递的字符。
- 在 C 中,以 0 开头的数字实际上是八进制而不是小数。所以 010 真的是十进制数字 8。
现在请注意,每当输出 _ 指针时,它都会与八进制值 073 进行异或运算。如果我们将其应用于整个字符串,我们会得到:
cCorsixcxCorsicixCorscsixCorcrsixCocorsixCcCorsixc
这开始类似于我们之前看到的输出。让我们继续分析一些更有趣的行:
for(l+=7; l != putchar(010); ++l); // 010 = 8 -> backspace char
这一行的重点是输出一系列退格。如果 l 等于 1,它将只输出一个退格键。但是,如果它等于其他东西,它就会疯狂地倾倒一卡车的字符。行为取决于 main 的调用方式。在启动时,它似乎总是以值 1 调用(不知道为什么)。
现在让我们看看递归主调用的组成部分。
( putchar(*_ ^ 073) | putchar(33) ) & 1 : // 33 = '!'
这是第一个可能的分支。首先它输出一个 XORed 字符,然后它输出一个“!”字符。如果您查看 33 的位模式,您会注意到 (x | 33) & 1 将始终计算为 1。因此在这种情况下,我们仅在 for 循环中输出一个退格字符。
另一方面,第二个分支有点棘手,因为传递给 main 的值不是 1。如果您仔细查看程序的输出,您会发现它确实在某个位置输出了一卡车的退格在字符串中。没有上下文,我无法真正说出目标是什么。
现在我们已经有了所有的部分,让我们重写代码:
#include <stdio.h>
#define BIG_CONSTANT 42 // Not the actual value.
int main () {
char* str = "cCorsixcxCorsicixCorscsixCorcrsixCocorsixCcCorsixc";
putchar(8);
char* c = str;
while (*c != '\0') {
if (*c != 'c') { // 'X' ^ 073 = 'c'
putchar(*c);
putchar('!');
putchar(8);
}
else {
for (int i = 0; i < BIG_CONSTANT; ++i)
putchar(8);
}
c++;
}
}
我的 C 有点生锈,所以它可能无法编译/运行。它仍然应该让您对正在发生的事情有一个很好的了解。
编辑:好吧,我发布答案有点晚了,我刚刚意识到我的控制台正在打印退格键,而不是仅仅删除字符。所以这就是为什么我有点误解了输出。所以就像接受的答案所说,如果你真的正确处理退格,它会打印 Corsix!。