Как и почему именно char * s2 изменяется после последнего вызова strcpy ()? - PullRequest
2 голосов
/ 09 июня 2019

Это один из вопросов, который может закончиться на тесте, который я собираюсь пройти через пару дней в школе. У меня возникли проблемы с пониманием того, как char * s2 меняется с "Службы сообщений" на "ice" после последнего вызова strcpy (). Я думаю, что это какое-то следствие указателей, но это все, что я знаю.

char s1[] = "Short Message Service";
char *s2, *s3;

s2 = strchr(s1, 'M');

s3 = strrchr(s2, 'S');

strncpy(s1 + 1, s2, 1);

strcpy(s1 + 2, s3);  

Я пытался отладить программу и наблюдать за переменными и указателями по мере их изменения, но я до сих пор не понимаю точно, как последний вызов влияет на char * s2.

Я ожидал, что значение s2 будет «Служба сообщений», но вместо этого фактический результат будет «льдом». Хотя я понимаю, как и почему меняются s1 и s3.

1 Ответ

4 голосов
/ 09 июня 2019

Если мы покажем массив с добавленными соответствующими указателями, он будет выглядеть примерно так:

+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+
| 'S' | 'h' | 'o' | 'r' | 't' | ' ' | 'M' | 'e' | 's' | 's' | 'a' | 'g' | 'e' | ' ' | 'S' | 'e' | 'r' | 'v' | 'i' | 'c' | 'e' | '\0' |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+
^                                   ^                                               ^
|                                   |                                               |
s1                                 s2                                               s3

Когда вы изменяете содержимое массива, сами указатели s2 и s3не изменяется, они по-прежнему указывают на те же места в массиве.

Так что после

strncpy(s1 + 1, s2, 1);

массив (с указателями) выглядит как

+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+
| 'S' | 'M' | 'o' | 'r' | 't' | ' ' | 'M' | 'e' | 's' | 's' | 'a' | 'g' | 'e' | ' ' | 'S' | 'e' | 'r' | 'v' | 'i' | 'c' | 'e' | '\0' |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+
^                                   ^                                               ^
|                                   |                                               |
s1                                 s2                                               s3

Единственный символ, на который указывает s2, копируется в s1[1].

Затем с

strcpy(s1 + 2, s3);  

массив выглядит как

+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+
| 'S' | 'M' | 'S' | 'e' | 'r' | 'v' | 'i' | 'c' | 'e' | '\0' | 'a' | 'g' | 'e' | ' ' | 'S' | 'e' | 'r' | 'v' | 'i' | 'c' | 'e' | '\0' |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+
^                                   ^                                                ^
|                                   |                                                |
s1                                 s2                                                s3

строка "Service" копируется по части строки, начинающейся с s1[2].

Указатель s2 все еще указывает на то же место, но если мы рассмотрим s2 как указатель на первый символстроки, ее содержимое изменилось, поскольку вы перезаписали это содержимое.

...