以字符串形式访问字符的模糊方式

时间:2010-09-23 16:43:43

标签: c++ obfuscation

我今天发现了一段有趣的代码:

auto ch = (double(), (float(), int()))["\t\a\r\n\0"]["abcdefghij"];

与...相同:

char str[] = "abcdefghij";
char ch = str['\t'];

为什么它甚至可能?特别是为什么编译器从字符串中挑选第一个char并将其用作下标而不是抛出错误?

2 个答案:

答案 0 :(得分:12)

首先,所有doublefloat内容都是纯误导。逗号运算符的返回值是其右侧参数,因此(double(), (float(), int()))归结为int(),尽管它在此过程中创建并丢弃doublefloat值。所以考虑一下:

 auto ch = int()["\t\a\r\n\0"]["abcdefghij"];

将评估的第一部分是

 int()["\t\a\r\n\0"]

现在,要认识到int()默认构造一个整数,赋值为0。所以声明等同于:

 0["\t\a\r\n\0"]

在C和C ++中,a[b]b[a]是等价的,这是一个众所周知的技巧,因为下标运算符定义为a[b] === *(a + b),并且加法是可交换的。所以这真的是:

 "\t\a\r\n\0"[0]

当然等于'\t'。现在完整的代码是:

 auto ch = '\t'["abcdefghij"];

出于同样的原因,相当于:

 auto ch = "abcdefghij"['\t'];

当然也可以写成

char str[] = "abcdefghij";
char ch = str['\t'];

如果您为“abcdefghij”字符串指定了名称,并在声明auto时使用了C ++ 0x ch关键字。

最后,请注意\t等于9,因为制表符的ASCII值为9,因此str['\t']str[9]相同。 str由10个字符组成,后跟一个NUL字符终止符(\0),它隐式添加到初始化的字符串文字中。

因此,在这两种情况下,ch的最终值均为'j'

答案 1 :(得分:8)

我会解释为重写:

auto ch = (double(), (float(), int()))["\t\a\r\n\0"]["abcdefghij"];

等同于(只用逗号运算符评估所有double, float, int临时值)

auto ch = (0["\t\a\r\n\0"])["abcdefghij"];

现在标准说:

x[y] == *(x + y)

无论哪一个是指针。所以你得到:

0["\t\a\r\n\0"] == "\t\a\r\n\0"[0] == '\t';