Я присваиваю значение непосредственно ячейке памяти с помощью переменной-указателя в C?

Я решил усложнить себе жизнь, выучив C. В настоящее время я пытаюсь полностью понять указатели.

Пока я так понимаю:

      #include <stdio.h>
int main() {

    char var = 'A';
    // Iniialize a pointer variable to the ADDRESS of variable "var"
    char *ptr = &var;
    printf("%c", var);    // Output: 'A'

    // Change the VALUE at the memory location of variable "var"
    *ptr = 'B';
    printf("%c", var);    // Output: 'B'

    return (0);
}

Но потом я искал возможность переназначить строку переменной и наткнулся на этот пост, где переменной-указателю присваивается значение напрямую.

Вот что я пытаюсь понять:

      #include <stdio.h>
int main() {

    // Declare a pointer variable
    char *ptr;

    // Assign a VALUE directly to a memory location???
    ptr = "String 1";
    printf("%s", ptr);    // Output: "String 1"

    return (0);
}

Кроме того, если я назначу новое строковое значение для ptr, такие как ptr = "String 2";, а также выводить место в памяти после каждого присваивания, я получаю другое место в памяти:

      #include <stdio.h>
int main() {

    // Declare a pointer variable
    char *ptr;

    // Assign a VALUE directly to a memory location???
    ptr = "String 1";
    printf("%s\n", ptr);    // Output: "String 1"
    printf("%p\n", ptr);    // Output: 0000000000404003 <- one memory location

    // Assign a new VALUE to the pointer variable
    ptr = "String 2";
    printf("%s\n", ptr);    // Output: "String 2"
    printf("%p", ptr);    // Output: 000000000040400F <- a new memory location

    return (0);
}

Действительно ли я присваиваю ЗНАЧЕНИЕ ячейке памяти, на которую ссылается переменная указателя?

Почему место в памяти меняется, когда я присваиваю новое значение переменной-указателю?

2 ответа

Чтобы присвоить значение объекту с помощью указателя, указывающего на объект, вам необходимо разыменовать указатель, как вы это делаете в первой программе.

      *ptr = 'B';

Что касается этого фрагмента кода

      char *ptr;

ptr = "String 1";

затем объявляется указатель, которому затем присваивается адрес первого символа строкового литерала "String 1".

Вы можете переназначить указатель, например

      ptr = "String 2";

но это переназначает сам указатель, а не объект, на который ранее указывал указатель. То есть теперь указатель указывает на первый символ строкового литерала "String 2".

Обратите внимание, что вы не можете изменить строковый литерал с помощью указателя, например,

      *ptr = 's';

Любая попытка изменить строковый литерал приводит к неопределенному поведению.

Но вы можете изменить массив символов, инициализированный строковым литералом, например

      char s[] = "String 1";
char *ptr = s;
*ptr = 's';

pointerхранить ссылку на (адрес) объекта.

      char *ptr = "string 1";

такой же как

      char *ptr;
ptr = "string 1";

он назначает указатель с адресом строкового литерала "string 1". Строковые литералы — это массивы, заканчивающиеся нулевым символом.

Когда ты :

      ptr = "string 2";

вы присваиваете указателю адрес другого строкового литерала. И как я писал выше это просто const charмножество. Адреса обоих строковых литералов различны.

       ptr = "String 2";
printf("%s\n", ptr);    // Output: "String 1"

Это невозможно, и вы публикуете здесь код, отличный от того, который вы запускаете на своем компьютере. Он будет печатать String 2для уверенности.

       // Assign a VALUE directly to a memory location???
ptr = "String 1";

Нет, это присваивание присваивает только указатель с адресом строкового литерала, который находится где-то в памяти. Он не выделяет место и не копирует эту строку куда-либо.

Магия:

Когда вы используете оператор разыменования *вы получаете доступ к объекту, на который ссылается указатель.

      char str[] = "String 1";
char *ptr;

ptr = str;
*ptr = 'X';

printf("str = `%s` And its address is %p\n", str, (void *)str);
printf("ptr = `%s` it is holging %p address. Its address is %p\n", ptr, (void *)ptr, (void *)&ptr);

Выход:

      str = `Xtring 1` And its address is 0x7ffdc9047827
ptr = `Xtring 1` it is holging 0x7ffdc9047827 address. Its address is 0x7ffdc9047818

Как вы видите, он меняет первый символ strкак указатель ptrсодержит адрес первого символа этого массива.

https://godbolt.org/z/x8PsW9vsP

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