struct student b[3] = { 18, "Peter", 19, "Mary", 20, "John" };
Создает массив struct student
с тремя элементами, которые, в зависимости от компилятора и дополнения, будет иметь sizeof
12-16 символов (x86_64) или 8-16 символов (x86), состоящие из 4-bytes
(int) и 8-bytes
(char *) (4 байта на x86) и будет иметь макет памяти чего-то вроде (например, целей):
int char*
+----+--------+----+--------+----+--------+
|age |name* |age |name* |age |name* |
+----+--------+----+--------+----+--------+
^
p
Отдельные строковые литералы ("Peter", "Mary", "John"
) создаются в памяти, а указатель на каждый строковый литерал хранится как name
в отдельных элементах структуры.
Когда вы используете оператор ->
, это является разыменованием для структуры. Использование оператора Преинкремента на p->age
, вы получите следующий возрастной элемент в массиве b
, но адрес указателя p
неизменен:
printf("%d\n", ++p->age);
+----+--------+----+--------+----+--------+
|age |name* |age |name* |age |name* |
+----+--------+----+--------+----+--------+
^ ^
p ++p->age
19
Разыменование p
и используя (точку) оператор '.'
, вы печатаете имя, связанное с текущим элементом в b
:
printf("%s\n", (*p).name);
Peter
Когда вы вычитать 1
из *p->name
вы декремент указателя на символ на 1
который оставляет вас в no-mans-land по адресу в памяти где-то перед строковым литералом «Питер».
printf("%c\n", *p->name - 1);
+----+--------+----+--------+----+--------+
|age |name* |age |name* |age |name* |
+----+--------+----+--------+----+--------+
^ \
p Peter (string literal in memory)
^
p->name - 1
0
Когда вы разыменования затем Преинкремент (вы увеличивающиеся указатель p->name
) вы перемещаете один символ вперед в строковый литерал «Питер»:
printf("%c\n", *++p->name);
+----+--------+----+--------+----+--------+
|age |name* |age |name* |age |name* |
+----+--------+----+--------+----+--------+
^ \
p Peter
^
++p->name
e
Когда вы в следующий раз разыменования, то после -increment, вы печатаете тот же символ, а затем опережения указатель на второй элемент в b
:
printf("%c\n", *p++->name);
+----+--------+----+--------+----+--------+
|age |name* |age |name* |age |name* |
+----+--------+----+--------+----+--------+
^ \
p Peter
^
p->name
e
+----+--------+----+--------+----+--------+
|age |name* |age |name* |age |name* |
+----+--------+----+--------+----+--------+
^
p
Наконец по operato г старшинство, вы Преинкремент указатель (опережения указатель на третий элемент в b
), а затем derefernce указатель p->name
указывая на J
:
printf("%c\n", *(++p)->name);
+----+--------+----+--------+----+--------+
|age |name* |age |name* |age |name* |
+----+--------+----+--------+----+--------+
^ \
p John
^
p->name
J
Я думаю, что я получаю это уже. Имя * p ++ -> сдвигает мой указатель, указывающий на Мэри, и следующее имя * (++ p) -> будет указывать на Джона. Я прав? –
Да, это звучит правильно. – tangrs
Большое вам спасибо! –