Я присваиваю значение непосредственно ячейке памяти с помощью переменной-указателя в 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
содержит адрес первого символа этого массива.