我今天发现了一段有趣的代码:
auto ch = (double(), (float(), int()))["\t\a\r\n\0"]["abcdefghij"];
与...相同:
char str[] = "abcdefghij";
char ch = str['\t'];
为什么它甚至可能?特别是为什么编译器从字符串中挑选第一个char并将其用作下标而不是抛出错误?
答案 0 :(得分:12)
首先,所有double
和float
内容都是纯误导。逗号运算符的返回值是其右侧参数,因此(double(), (float(), int()))
归结为int()
,尽管它在此过程中创建并丢弃double
和float
值。所以考虑一下:
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';