访问字符串中字符的混淆方式
我今天发现了一段有趣的代码:
auto ch = (double(), (float(), int()))["\t\a\r\n\0"]["abcdefghij"];
其工作原理与:
char str[] = "abcdefghij";
char ch = str['\t'];
为什么它是可能的?特别是为什么编译器从字符串中选取第一个字符并将其用作下标而不是抛出错误?
I found today interesting piece of code:
auto ch = (double(), (float(), int()))["\t\a\r\n\0"]["abcdefghij"];
which works same as:
char str[] = "abcdefghij";
char ch = str['\t'];
Why is it even possible? Especially why is the compiler picking first char from string and using it as subscript instead of throwing error?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,所有那些
double
和float
的东西纯粹是误导。逗号运算符的返回值是其右侧参数,因此(double(), (float(), int()))
归结为int()
,尽管它在此过程中创建并丢弃了一个 double 和一个 float 值。因此,请考虑:将要评估的第一部分是
现在,认识到
int()
默认构造一个整数,它赋予它值0
。因此,该语句等效于:这是 C 和 C++ 中众所周知的技巧,
a[b]
和b[a]
是等效的,因为定义了下标运算符为a[b] === *(a + b)
并且加法是可交换的。所以这实际上与:这当然等于
'\t'
。现在完整的代码是:出于同样的原因,它相当于:
当然也可以写成
如果您给“abcdefghij”字符串一个名称并放弃使用 C++0x
auto<声明
ch
时使用 /code> 关键字。最后,请注意
\t
等于 9,因为制表符的 ASCII 值为 9,因此str['\t']
与str[ 相同9]
。str
由 10 个字符组成,后跟一个 NUL 字符终止符 (\0
),它隐式添加到初始化时使用的字符串文字中。因此,在这两种情况下,
ch
的最终值为'j'
。So first of all, all that
double
andfloat
stuff is pure misdirection. The comma operator's return value is its right-side argument, so(double(), (float(), int()))
boils down to justint()
, although it creates and discards adouble
and afloat
value along the way. So consider:The first part of this that will be evaluated is
Now, recognize that
int()
default-constructs an integer, which gives it the value0
. So the statement is equivalent to:It's a fairly well known trick in C and C++ that
a[b]
andb[a]
are equivalent, since the subscript operator is defined asa[b] === *(a + b)
and addition is commutative. So this is really the same as:which is of course equal to
'\t'
. Now the full piece of code is:which for the same reason is equivalent to:
Which of course could also be written as
If you gave the "abcdefghij" string a name and forwent the use of the C++0x
auto
keyword when declaringch
.Finally, note that
\t
is equal to 9 since the tab character has ASCII value 9, sostr['\t']
is the same asstr[9]
.str
consists of 10 characters followed by a NUL character terminator (\0
), which is implicitly added to the string literal that it was initialized with.So in both cases the final value of
ch
is'j'
.我将解释为重写:
相当于(只需用逗号运算符评估所有
double,float,int
临时值)现在标准说:
无论哪一个都是指针。所以你得到:
I'll explain as rewrite:
is equivalent to (just evaluate all the
double, float, int
temporaries with comma operator)Now the standard says that:
No matter which one is a pointer. so you get: