Почему т указывает на букву С? - PullRequest
0 голосов
/ 22 декабря 2018

Я хочу прочитать мою строку в обратном направлении.Я сделал это, но я не понимаю, как работают две части моего кода.

char s1[] = "ABC";
printf("%s", s1);
size_t len = strlen(s1);
printf("\n%d", len);

char *t = s1 + len - 1;
printf("\n%s\n", t);

while (t>=s1)
{
    printf("%c", *t);
    t = t - 1;
}
  • Первый: как t указывает на букву C?
  • Второе: как можно добавить переменную len, которая содержит целое число, с массивом, который содержит литералы?Это потому, что указатель t добавляет свои адреса, используя арифметику указателей?

Ответы [ 3 ]

0 голосов
/ 22 декабря 2018

В языке C массивы немного странные.В массиве-х может очень легко перейти к указателю на х, очень легко.Например, если вы переходите к другой подпрограмме, или как в вашем случае при добавлении к ней.Так что вы правы, это указатель арифметики.(В арифметике указателей вы можете добавлять указатели и целые числа, чтобы получить указатели.)

0 голосов
/ 22 декабря 2018

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.
0 голосов
/ 22 декабря 2018

Это

char s1[] = "ABC";

выглядит как

 0x100   0x101  0x102   0x103 . . . .Assume 0x100 is base address of s1
 --------------------------------
|   A   |   B   |   C   |   \0   |
 --------------------------------
s1

Здесь s1, который является массивом символов, указывает на базовый адрес 0x100 (предположим).

Я хочу прочитать мою строку в обратном порядке?

Для этого вам нужно, чтобы кто-то указал на местоположение 0x102, то есть последний элемент массива, для этого

size_t len = strlen(s1); /* finding length of array s1 i.e it returns 3 here */
char *t = s1 + len - 1; /* (0x100 + 3*1) - 1 i.e char pointer t points to 0x102 */

над двумя строками кода написано.Теперь это выглядит как

 0x100   0x101  0x102   0x103 . . . . 
 --------------------------------
|   A   |   B   |   C   |   \0   |
 --------------------------------
s1                  t <-- t points here

Теперь, когда вы делаете *t, оно печатает значение char в t местоположении, т.е. в 0x102, то есть печатает C, в следующей итерации вам нужнонапечатайте символ на одну позицию назад, для этого вы делаете t = t - 1;.

Примечание: Здесь

char *t = s1 + len - 1;

s1 - это указатель на символ * , а len - это целочисленная переменная поэтому, когда вы делаете арифметику указателя , она автоматически увеличивается на размер данных, на которые указывает указатель.Например,

char *t = s1 + len;

оценивается как

t = 0x100 + 3*sizeof(*s1); ==> 0x100 + 3*1  ==> 0x103
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...