Запутанный способ доступа к символу в строке - PullRequest
7 голосов
/ 23 сентября 2010

Я нашел сегодня интересный кусок кода:

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

, который работает так же, как:

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

Почему это вообще возможно?Особенно, почему компилятор выбирает первый символ из строки и использует его как индекс, а не выдает ошибку?

Ответы [ 2 ]

12 голосов
/ 23 сентября 2010

Итак, во-первых, все эти вещи double и float - это просто неверное направление.Возвращаемое значение оператора запятой является его аргументом в правой части, поэтому (double(), (float(), int())) сводится к int(), хотя при этом он создает и отбрасывает значения double и float.Итак, рассмотрим:

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

Первая часть этого, которая будет оценена, это

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

Теперь, признайте, что int() default-строит целое число, которое дает ему значение 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.

Наконец, обратите внимание, что \t равно 9, посколькусимвол табуляции имеет значение ASCII 9, поэтому str['\t'] совпадает с str[9].str состоит из 10 символов, за которыми следует символ NUL (\0), который неявно добавляется к строковому литералу, с которым он был инициализирован.

Таким образом, в обоих случаях конечное значение ch'j'.

8 голосов
/ 23 сентября 2010

Я объясню как переписать:

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