char s1[] = "ABC";
s1
- это массив из 4 символов char[4]
со значениями {'A','B','C','\0'}
size_t len = strlen(s1);
s1
"распад"(читай: автоматически преобразуется) из массива типа в указатель на тип.Таким образом, s1
распадается из массива из 4 символов в указатель на первый символ массива.
strlen
подсчитывает количество байтов до того, как встретит нулевой байтовый разделитель '\0'
.Начиная с 'A'
мы можем считать 'A'
, 'B'
, 'C'
- это len = 3
.
Указатели в C являются обычными целыми числами (хорошо, на большинстве архитектур).Вы можете добавить к ним и вычесть их, и использовать uintptr_t
, чтобы преобразовать их в целое число.Но добавление к ним без приведения будет использовать «арифметику указателей», это означает, что (int*)5 + 2
соответствует значению, равному 5 + 2 * sizeof(int)
.
char *t = s1 + len - 1;
s1
распадается науказатель на первый символ в массиве s1
, это 'A'
.Мы добавляем + (len = 3)
, это означает, что s1 + 3
указывает на байт, содержащий '\0'
внутри массива s1 = (char[4]){'A','B','C','\0'}
.Затем мы вычитаем - 1
, поэтому t
теперь будет указывать на байт, содержащий символ 'C'
внутри массива s1
.
while (t >= s1) {
... *t ...
t = t - 1;
}
Начало: s1
указывает на 'A'
.t
указывает на 'C'
.
, а: t
больше s1
.Двумя.t - s1 = 2
, т.е.s1 + 2 = t
loop: *t
равно 'C'
.
, декремент: t--
, поэтому теперь t
будет указывать на 'B'
.
, тогда как: t
больше s1
,По onw.
loop: *t
равно 'B'
.
, декремент: тогда t--
, так что теперь t
будет указывать на 'A'
.
, а: сейчас t
равен тогда s1
.Оба указывают на первый символ массива.
loop: *t
равно 'B'
.
Уменьшение: Тогда t--
, так что теперь t
будет указывать на неизвестное местоположение перед массивом.Поскольку указатели
(на большинстве архитектур) являются простыми целыми числами, вы можете уменьшать и увеличивать их как обычные переменные.
, а: t
теперь ниже s1
.Цикл заканчивается.
Примечания:
printf("\n%d", len);
- неопределенное поведение и порождает носовые демоны .Используйте printf("\n%zu", len);
, чтобы напечатать переменную size_t
. - Вы можете напечатать значение указателя, используя спецификатор
%p
и приведя к void printf("%p", (void*)t)
t = s1 - 1
.Присвоение указателя одному элементу перед массивом является неопределенным поведением в C. Это происходит в конечном состоянии цикла, когда t = t - 1
.Измените на do { .. } while
loop.