Указатель, кажется, не синхронизируется с выводом printf

Мне трудно понять, что содержит pointer2. Второй printf печатает llo World, а третий печатает Hey you guys!. Почему так, если strcpy копирует y you guys!\n в llo World. Насколько я понимаю приведенную ниже программу, последним выводом должен быть llo Worldy you guys!\n, не так ли?

int main() 
{
    char str_a[20];  // a 20 element character array
    char *pointer;   // a pointer, meant for a character array
    char *pointer2;  // and yet another one

    strcpy(str_a, "Hello World\n");

    pointer = str_a; // set the first pointer to the start of the array
    printf("%p\n", pointer);

    pointer2 = pointer + 2; // set the second one 2 bytes further in
    printf("%s", pointer2);       // print it

    strcpy(pointer2, "y you guys!\n"); // copy into that spot
    printf("%s", pointer);        // print again
}

Во-первых, добро пожаловать в StackOverflow. pointer2 содержит адрес первого l в Hello World строке. После его однократной печати данные, на которые он указывает, перезаписываются строкой y you guys! Строка записывается в память, начиная с pointer2

Caglayan DOKME 08.04.2022 18:39

Почему вы ожидаете, что strcpy добавит строку в конец? Кроме того, ваш массив может содержать только 20 символов. Вы ожидаете, что он будет держать больше, чем это.

Gerhardh 08.04.2022 18:43

@CaglayanDOKME Как изменяется pointer? strcpy не заморачивайтесь.

userfaultfd 08.04.2022 18:44
pointer не изменяется. Он указывает на str_a так же, как pointer2 указывает на массив. Этот массив изменен.
Gerhardh 08.04.2022 18:46

@Gerhardh Я думаю, у меня неправильное представление о том, что на самом деле делает pointer + 2 .. Какую часть строки он занимает, He или остальное?

userfaultfd 08.04.2022 18:49

нвм мальчики. спасибо тебе

userfaultfd 08.04.2022 19:00
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
41
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Указатель pointer указывает на первый символ массива str_a.

pointer = str_a;

Массив содержит строку "Hello World\n".

Указатель pointer2 указывает на третий элемент строки

pointer2 = pointer + 2;

то есть он указывает на "llo World\n".

Затем эта подстрока перезаписывается, сохраняя неизменными str_a[0] и str_a[1].

strcpy(pointer2, "y you guys!\n");

Итак, массив str_a содержит строку "Hey you guys!\n"

На самом деле приведенный выше вызов strcpy эквивалентен

strcpy( &str_a[2], "y you guys!\n");

потому что, в свою очередь, это утверждение

pointer2 = pointer + 2;

эквивалентно

pointer2 = &str_a[2];

или

pointer2 = &pointer[2];

И этот звонок

printf("%s", pointer); 

выводит строку.

То есть "He" (начиная с str_a[0]) плюс "y you guys!\n" (начиная с str_a[2]) дает результирующую строку.

Где ждет He? Почему добавляется He, а не остальная часть строки, которая была сокращена pointer2?

userfaultfd 08.04.2022 18:47

@userfaultfd Элементы массива str_a[0] и str_a[1] не были перезаписаны. Новая строка была записана, начиная с str_a[2]. И указатель-указатель выводит массив результатов, начиная с str_a[0].

Vlad from Moscow 08.04.2022 18:50

Ага, теперь я понимаю. Моя проблема заключалась в том, что я думал, что указатель сам по себе является объектом. Я не знал, что при strcpyнаведении указателя место, на которое он указывает, также изменяется. Нужно вернуться к указателям ig.

userfaultfd 08.04.2022 18:56

@userfaultfd: указатель — это объект сам по себе, тот, который указывает на другой объект, strcpy изменяет объект, на который указывает указатель, а не указатель (он остается неизменным)

Chris Dodd 08.04.2022 20:10
char str_a[20];  // a 20 element character array
char *pointer;   // a pointer, meant for a character array
char *pointer2;  // and yet another one

Первая строка создает и выделяет память на 20 символов. Два других только создают указатели ни на что. Эти указатели можно использовать для указания на область памяти, что означает, что вы можете хранить в них адрес (число).

strcpy(str_a, "Hello World\n");

Эту строку скопируйте "Hello World\n" в str_a (выделенная память - ОК).

pointer = str_a; // set the first pointer to the start of the array
printf("%p\n", pointer);

Теперь мы копируем адрес str_a в переменную указатель. Эти две переменные можно использовать одинаково. Они указывают на одно и то же воспоминание. Указанный адрес памяти печатается.

pointer2 = pointer + 2; // set the second one 2 bytes further in
printf("%s", pointer2);       // print it

Здесь мы тоже копируем адрес (число), как это делалось раньше, но добавляем 2 к адресу de. Итак, если str_a и указатель указывают на позицию X, то теперь указатель2 будет указывать на X+2 (X — число, адрес блока памяти). Мы знаем, что этот блок (str_a) имеет содержимое "Hello World\n", а затем указатель2 указывает на позицию на 2 символа вправо: "llo World\n". Это означает, что номер адреса, хранящийся в указатель2, указывает на эту позицию, но выделенный блок еще содержит все предложение.

strcpy(pointer2, "y you guys!\n"); // copy into that spot
printf("%s", pointer);        // print again

Теперь мы можем видеть копию символов по адресу, указанному указатель2. Таким образом, первые два символа находятся за пределами места копирования, а «y you, ребята!\n» будет скопировано в позицию 2 str_a, то есть в позицию 0 указатель2.

Результат: "He" (два первых символа str_a не тронуты) + "y, ребята!\n" (символы скопированы в указатель2) = "Эй, ребята!\n"

Если вы напечатаете указатель2, вы увидите "у вас, ребята!\n".

Спасибо, Алекс. Теперь я понимаю гораздо больше.

userfaultfd 08.04.2022 19:15

Другие вопросы по теме