Может кто-нибудь объяснить, почему printf ("% s", str + str [0] - str [3]); работает в C? - PullRequest
2 голосов
/ 06 февраля 2020
char *str = "ESPA1";
printf("%s", str + str[0] - str[3]);

Я знаю, что вывод равен 1 , но я не понимаю, почему можно "вырезать" часть строки следующим образом.

Ответы [ 2 ]

7 голосов
/ 06 февраля 2020

Сначала давайте разберем выражение:

str + str[0] - str[3]

Подставляя значения str[0] и str[3], мы получим:

str + 'E' - 'A'

Предполагая, что символы представлены в ASCII, это то же самое, что:

str + 69 - 65

Теперь мы возьмем быстрый ярлык и предположим, что это то же самое, что и:

str + (69 - 65)

Что дает нам:

str + 4

Указатель на индекс элемента 4 массива, а именно символ '1'. Итак, printf начинает читать оттуда, и вот что печатается.


Теперь вернемся к этому ярлыку:

str + (69 - 65)

Это не то, как это на самом деле рассчитывается. Сложение и вычитание имеют одинаковый уровень приоритета и группу слева направо, так что это действительно:

(str + 69) - 65

Первое подвыражение генерирует указатель на индекс 69, однако строковый литерал, на который указывает str, не указывает не так много элементов. Поэтому, поскольку мы создаем указатель более чем на 1 элемент после конца массива, код демонстрирует неопределенное поведение . Вам «повезло» в этом деле, что это сработало как положено.

3 голосов
/ 06 февраля 2020

Посмотрите на это:

char *str = "ESPA1";
printf("%s", str + 4); 

Значение Ascii 'A' равно 65, а 'E' равно 69, таким образом, вычитание дает 4, и вы ссылаетесь на элемент 5th из базы str который, конечно, является местоположением / ссылкой первого элемента.

Чтобы узнать больше об арифметике указателя c:

Арифметика указателя c

ASCII Таблица

...