#c #pointers
#c #указатели
Вопрос:
Это фрагмент кода, который я создал в целях изучения C , в настоящее время я пытаюсь обучить себя. Мой вопрос в том:
Почему *ptr = 30
изменяются выходные значения двух последних инструкций cout в моем main? (результат равен 30, 30, 30). Следовательно, почему int y = 30;
и ptr = amp;y;
не изменяют выходные данные в моем main и остаются локальными для функции? (если я закомментирую *ptr = 30, а не два предыдущих оператора, результат будет 30, 5, 5)
Если я изменю ввод функции на void printPointer(int *amp;fptr)
— и закомментирую только *ptr = 30
— тогда *ptr
в моем main будут изменены, но не x. Я понимаю это, поскольку передача по ссылке изменяет указатель, но не так, как мой первый оператор изменяет * ptr и x в моем main.
#include <iostream>
using namespace std;
void printPointer(int *fptr);
int main()
{
int x = 5;
int *ptr = amp;x;
printPointer(ptr);
cout << *ptr << endl;
cout << x << endl;
return 0;
}
void printPointer(int *fptr)
{
// int y = 30; // this does not change the output of the last two couts in main, output = 30, 5, 5
// fptr = amp;y;
*fptr = 30; // uncommenting this and commenting out the former two statements: output = 30, 30, 30
cout << *fptr << endl;
}
Ответ №1:
*ptr = 30
изменяет значение того, на что указывается. В вашем случае вы установили ptr
значение указывать на x
(когда вы это сделали ptr = amp;x
, а затем передали это в качестве аргумента printPointer()
). Таким образом, значение x
изменено.
Когда вы вместо этого делаете int y = 30; fptr = amp;y;
, все, что вы делаете, это изменяете fptr
, чтобы указывать на другую переменную. Вот и все. Вы не меняете значение того, на что указывается (т.Е. значение x
). И вы не влияете ptr
, потому что fptr
это отдельная локальная переменная. Таким образом, ptr
все еще указывает на x
, и x
по-прежнему равно 5.
Когда вы изменяете свою функцию, чтобы принимать указатель по ссылке, то изменение fptr
на point at y
также меняется ptr
, потому что это одна и та же переменная.
Комментарии:
1. Поэтому, когда я делаю *fptr = 30, я изменяю фактическое значение, хранящееся в адресе памяти fptr, который также является тем же адресом памяти, где расположены x и ptr, таким образом изменяя их в будущих выводах. Однако int y = 30; и ftpr = amp;y являются локальными для функции и исчезают после завершения вызова функции.
2. @Antonious: Если быть педантичным, когда вы это делаете
*fptr = 30
, вы изменяете значение, хранящееся по адресу, на который указываетfptr
, который является тем же адресом, на который указываетptr
, и который является фактическим адресомx
.
Ответ №2:
*fptr = 30
разыменовал бы адрес, хранящийся в fptr
, и записал бы 30 в позицию в памяти. этот адрес в памяти вы передали функции с помощью printPointer(ptr)
. ptr
в данном случае это был адрес x, который вы присвоили ptr с помощью ptr = amp;x
.
int y= y
объявляет переменную, локальную для функции. fptr = amp;y
присваивает адрес y fptr (и перезаписывает значение из ptr). таким образом, последняя строка в этом случае изменила бы локальную переменную y вместо x.
Ответ №3:
Если я правильно понимаю, вы спрашиваете о двух фрагментах кода. Первый — это то, что вы опубликовали:
#include <iostream>
using std::cout;
void f(int* fptr) {
*fptr = 30; // 11
cout << "*fptr = " << *fptr << 'n'; // 12
}
int main() {
int x = 5; // 1
int* ptr = amp;x; // 2
f(ptr); // 21
cout << "*ptr = " << *ptr << 'n'; // 22
cout << "x = " << x << 'n'; // 23
}
В этом случае указатель всегда указывает на x, и в функции вы все равно изменяете значение x, поскольку именно на это указывает fptr. Если это поможет, вот демонстрация значения переменных в конце каждой строки: NE означает, что переменная в данный момент не существует.
1. x = 5, ptr = NE, fptr = NE
2. x = 5, ptr = amp;x, fptr = NE
11. x = 30, ptr = amp;x, fptr = amp;x
12. x = 30, ptr = amp;x, fptr = amp;x
21. x = 30, ptr = amp;x, fptr = NE
После этого значения не изменяются, и все три оператора будут печатать 30.
Второй из них:
#include <iostream>
using std::cout;
void f(int*amp; fptr) {
int y = 30; // 11
fptr = amp;y; // 12
cout << "*fptr = " << *fptr << 'n'; // 13
}
int main() {
int x = 5; // 1
int* ptr = amp;x; // 2
f(ptr); // 21
cout << "*ptr = " << *ptr << 'n'; // 22
cout << "x = " << x << 'n'; // 23
}
В первом случае указатель передается по ссылке, и он указывает на y . Фактически, в этом случае строка 21 предполагает неопределенное поведение, поскольку y больше не существует. Опять же, построчный анализ:
1. x = 5, y = NE, ptr = NE, fptr == NE
2. x = 5, y = NE, ptr = amp;x, fptr == NE
11. x = 5, y = 30, ptr = amp;x, fptr == ptr
12. x = 5, y = 30, ptr = amp;y, fptr == ptr
13. x = 5, y = 30, ptr = amp;y, fptr == ptr
21. x = 5, y = NE, ptr = amp;y, fptr == NE
После этого значения снова не меняются: однако в строке 22 вы пытаетесь получить адрес ptr
. Как вы можете видеть, *ptr = y = NE
, и, следовательно, поведение не определено. Вывод может быть любым.
(Еще одно замечание заключается в том, что вам следует избегать, using namespace std;
поскольку это может привести к конфликтам имен; используйте using std::cout;
и аналогичные, как в приведенном выше коде.)