Предположим, у вас есть этот массив:
char a[10];
Мы можем представить, что это выглядит так:
+---+---+---+---+---+---+---+---+---+---+
a: | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+
Предположим, вы вызываете scanf
, чтобы прочитать строку в массив:
scanf("%s", a);
Предположим, вы набрали "привет".Массив заполняется так:
+---+---+---+---+---+---+---+---+---+---+
a: | h | e | l | l | o |\0 | | | | |
+---+---+---+---+---+---+---+---+---+---+
Предположим, вы установили указатель, указывающий на массив, и передали этот указатель в scanf
:
char b[10];
char *p = b;
scanf("%s", p);
Теперь точно так жепроисходит: p
указывает на начало строки, поэтому scanf
хранит строку, которую она читает:
+---+---+---+---+---+---+---+---+---+---+
b: | h | e | l | l | o |\0 | | | | |
+---+---+---+---+---+---+---+---+---+---+
^
+-----|-----+
p: | * |
+-----------+
Наконец, предположим, что у нас есть другой массив и другой указатель, но вместо передачиуказатель на scanf
, мы добавляем 1 к указателю перед передачей его на scanf
:
char c[10];
char *ss = c;
scanf("%s", ss + 1);
Теперь scanf
получает указатель на вторую ячейку в массивевот где она записывает строку:
+---+---+---+---+---+---+---+---+---+---+
c: | | h | e | l | l | o |\0 | | | |
+---+---+---+---+---+---+---+---+---+---+
^
+-----|-----+
ss: | * |
+-----------+
Это немного сбивает с толку.Проще увидеть, если мы сделаем сложение в стороне.Также легче увидеть, если мы предварительно заполним массив некоторыми другими символами:
char d[10] = "rstuvwxyz";
Итак, изначально d
выглядит так:
+---+---+---+---+---+---+---+---+---+---+
d: | r | s | t | u | v | w | x | y | z |\0 |
+---+---+---+---+---+---+---+---+---+---+
Теперь, если мы сделаем это,и снова введите «привет»:
char *p1 = d;
char *p2 = p1 + 1;
scanf("%s", p2);
в итоге получается картинка, которая выглядит следующим образом:
+-----------+
p1: | * |
+-----|-----+
|
v
+---+---+---+---+---+---+---+---+---+---+
d: | r | h | e | l | l | o |\0 | y | z |\0 |
+---+---+---+---+---+---+---+---+---+---+
^
+-----|-----+
p2: | * |
+-----------+
scanf
читает где p2
указывает, что является одниммимо, где p1
указывает, что находится в начале массива d
.
Если вы хотите подтвердить, что происходит, вы можете сделать printf("%s\n", d)
.Если вы сделаете это до вызова scanf
, он должен вывести rstuvwxyz
, а если вы сделаете это после вызова scanf
(и если вы продолжите набирать «привет»), он должен вывести rhello
.
Поначалу все может показаться довольно загадочным, но это простое применение арифметики указателей .(Когда я говорю такие вещи, как p = b
, где p
- это указатель, а b
- это массив, а указатель заканчивается указанием на первый символ массива.специальное правило в C, о котором вы захотите узнать в скором времени.)
Есть еще один большой вопрос без ответа, а именно , почему кто-то захочет написать код таким образом,Это сложнее объяснить.Одна возможность, которую я могу себе представить, состоит в том, что она была частью более крупной программы, которая по какой-то причине пыталась сохранить много строк в одном массиве, например:
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
longer_array: | c | a | t |\0 | d | o | g |\0 | c | o | w |\0 | b | e | a | r |\0 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
Если в более крупной программе,указатель ss
указывает на \0
a конец предыдущей прочитанной строки, тогда ss + 1
- действительно правильное место для начала чтения следующей.
(Но я размышляю.Не видя большую программу, невозможно понять, почему она захотела прочитать в ss + 1
. Действительно, это необычно.)