访问字符串中字符的混淆方式

发布于 2024-09-24 12:30:20 字数 259 浏览 2 评论 0原文

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

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一笔一画续写前缘 2024-10-01 12:30:20

首先,所有那些 doublefloat 的东西纯粹是误导。逗号运算符的返回值是其右侧参数,因此 (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”字符串一个名称并放弃使用 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 and float stuff is pure misdirection. The comma operator's return value is its right-side argument, so (double(), (float(), int())) boils down to just int(), although it creates and discards a double and a float value along the way. So consider:

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

The first part of this that will be evaluated is

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

Now, recognize that int() default-constructs an integer, which gives it the value 0. So the statement is equivalent to:

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

It's a fairly well known trick in C and C++ that a[b] and b[a] are equivalent, since the subscript operator is defined as a[b] === *(a + b) and addition is commutative. So this is really the same as:

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

which is of course equal to '\t'. Now the full piece of code is:

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

which for the same reason is equivalent to:

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

Which of course could also be written as

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

If you gave the "abcdefghij" string a name and forwent the use of the C++0x auto keyword when declaring ch.

Finally, note that \t is equal to 9 since the tab character has ASCII value 9, so str['\t'] is the same as str[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'.

满意归宿 2024-10-01 12:30:20

我将解释为重写:

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';

I'll explain as rewrite:

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

is equivalent to (just evaluate all the double, float, int temporaries with comma operator)

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

Now the standard says that:

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

No matter which one is a pointer. so you get:

0["\t\a\r\n\0"] == "\t\a\r\n\0"[0] == '\t';
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文