포인터 설명을 가리키는 포인터
포인터에 대한 포인터의 작동 방식에 대한 이 자습서 를 따르고있었습니다 .
관련 구절을 인용하겠습니다.
int i = 5, j = 6, k = 7; int *ip1 = &i, *ip2 = &j;
이제 우리는 설정할 수 있습니다
int **ipp = &ip1;
및
ipp
포인트ip1
에있는 점i
.*ipp
isip1
, and**ipp
isi
또는 5입니다. 다음과 같이 익숙한 상자 및 화살표 표기법으로 상황을 설명 할 수 있습니다.
그렇다면 우리는 말합니다
*ipp = ip2;
우리가 가리키는 포인터 변경했습니다
ipp
(즉,ip1
의 사본을 포함)을ip2
, 그래서 그것을 (ip1
) 지금 시점에서j
:
내 질문은 : 왜 두 번째 그림에서 ipp
여전히 가리키고 ip1
있지만 그렇지 ip2
않습니까?
포인팅 비유에 대해 잠시 잊어 버려요. 포인터가 실제로 포함하는 것은 메모리 주소입니다. 는 &
연산자 "주소"입니다 - 객체의 메모리 주소를 반환 즉. *
운영자는 해당 메모리 주소의 객체를 반환, 포인터, 주소를 포함하는 포인터를 제공하여 예를 의미 당신에게 객체를 제공합니다. 당신이 그래서 *ipp = ip2
, 당신이하고있는 것은 *ipp
개최 된 주소의 객체를 얻을 수있는 ipp
이는 ip1
다음에 할당 ip1
에 저장된 값 ip2
의 주소입니다 j
.
간단히
&
-> 주소
*
-> 값
의 값이 ipp
아닌 에 의해 지정된 값을 변경했기 때문 입니다 ipp
. 따라서 ipp
여전히 ip1
(의 값 ipp
) 을 (를 ) 가리키는 ip1
값은 이제 값과 동일 ip2
하므로 둘 다를 가리 킵니다 j
.
이:
*ipp = ip2;
와 같다:
ip1 = ip2;
이 코드가 도움이되기를 바랍니다.
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int i = 5, j = 6, k = 7;
int *ip1 = &i, *ip2 = &j;
int** ipp = &ip1;
printf("address of value i: %p\n", &i);
printf("address of value j: %p\n", &j);
printf("value ip1: %p\n", ip1);
printf("value ip2: %p\n", ip2);
printf("value ipp: %p\n", ipp);
printf("address value of ipp: %p\n", *ipp);
printf("value of address value of ipp: %d\n", **ipp);
*ipp = ip2;
printf("value ipp: %p\n", ipp);
printf("address value of ipp: %p\n", *ipp);
printf("value of address value of ipp: %d\n", **ipp);
}
출력 :
C 태그의 초보자 질문과 마찬가지로이 질문은 첫 번째 원칙으로 돌아가서 답변 할 수 있습니다.
- 포인터는 일종의 가치입니다.
- 변수는 값을 포함합니다.
&
연산자는 포인터에 가변 변.*
조작 변수에 대한 포인터를 온.
(기술적으로는 "variable"대신 "lvalue"라고 말해야하지만 가변 스토리지 위치를 "variables"로 설명하는 것이 더 명확하다고 생각합니다.
그래서 우리는 변수가 있습니다 :
int i = 5, j = 6;
int *ip1 = &i, *ip2 = &j;
변수 는 포인터를 ip1
포함 합니다. &
연산자 변 i
포인터에 해당 포인터 값이 할당된다 ip1
. 그래서 ip1
포함 에 대한 포인터를 i
.
변수 는 포인터를 ip2
포함 합니다. &
연산자 변 j
포인터에 해당 포인터에 할당된다 ip2
. 그래서 ip2
포함 에 대한 포인터를 j
.
int **ipp = &ip1;
변수 ipp
는 포인터를 포함합니다. &
연산자 가변 변 ip1
포인터에 해당 포인터 값이 할당된다 ipp
. 그래서 ipp
에 대한 포인터를 포함합니다 ip1
.
지금까지 이야기를 요약 해 봅시다.
i
5 개 포함j
6을 포함ip1
"포인터i
"를 포함ip2
"포인터j
"를 포함ipp
"포인터ip1
"를 포함
이제 우리는 말합니다
*ipp = ip2;
*
연산자 변수로 포인터를 다시 온. 우리 ipp
는 "의 포인터를 가져 와서 ip1
변수로 바꾸는 값 "을 가져옵니다 . ip1
물론 어떤 변수입니까?
따라서 이것은 단순히 다른 표현 방법입니다
ip1 = ip2;
따라서 값을 가져옵니다 ip2
. 무엇입니까? "포인터 j
" 해당 포인터 값을에 할당 ip1
하므로 ip1
이제는 "포인터 j
"
한 가지만 변경했습니다 : 값 ip1
:
i
5 개 포함j
6을 포함ip1
"포인터j
"를 포함ip2
"포인터j
"를 포함ipp
"포인터ip1
"를 포함
왜
ipp
아직도 가리키고ip1
있지ip2
않습니까?
변수를 할당하면 변경됩니다. 과제를 세십시오. 할당보다 변수에 더 많은 변화가있을 수 없습니다! 당신은에 할당하여 시작 i
, j
, ip1
, ip2
와 ipp
. 그런 다음에 할당하면 *ipp
"할당"과 같은 의미 ip1
입니다. ipp
두 번째로 할당 하지 않았으므로 변경되지 않았습니다!
변경 ipp
하고 싶다면 실제로 다음을 할당해야합니다 ipp
.
ipp = &ip2;
예를 들어.
저의 개인적인 견해는 화살표가이 방법을 가리 키거나 포인터를 이해하기 어렵게 만드는 그림입니다. 그것들을 추상적이고 신비한 존재처럼 보이게합니다. 그들은 아닙니다.
Like everything else in your computer, pointers are numbers. The name "pointer" is just a fancy way of saying "a variable containing an address".
Therefore, let me stir things around by explaining how a computer actually works.
We have an int
, it has the name i
and the value 5. This is stored in memory. Like everything stored in memory, it needs an address, or we wouldn't be able to find it. Lets say i
ends up at address 0x12345678 and its buddy j
with value 6 ends up just after it. Assuming a 32-bit CPU where int is 4 bytes and pointers are 4 bytes, then the variables are stored in physical memory like this:
Address Data Meaning
0x12345678 00 00 00 05 // The variable i
0x1234567C 00 00 00 06 // The variable j
Now we want to point at these variables. We create one pointer to int, int* ip1
, and one int* ip2
. Like everything in the computer, these pointer variables get allocated somewhere in memory too. Lets assume they end up at the next adjacent addresses in memory, immediately after j
. We set the pointers to contain the addresses of the variables previously allocated: ip1=&i;
("copy the address of i into ip1") and ip2=&j
. What happens between the lines is:
Address Data Meaning
0x12345680 12 34 56 78 // The variable ip1(equal to address of i)
0x12345684 12 34 56 7C // The variable ip2(equal to address of j)
So what we got were just yet some 4 byte chunks of memory containing numbers. There's no mystical or magical arrows anywhere in sight.
In fact, just by looking at a memory dump, we can't tell whether the address 0x12345680 contains an int
or int*
. The difference is how our program chooses to use the contents stored at this address. (The task of our program is actually just to tell the CPU what to do with these numbers.)
Then we add yet another level of indirection with int** ipp = &ip1;
. Again, we just get a chunk of memory:
Address Data Meaning
0x12345688 12 34 56 80 // The variable ipp
The pattern does seem familiar. Yet another chunk of 4 bytes containing a number.
Now, if we had a memory dump of the above fictional little RAM, we could manually check where these pointers point. We peek at what's stored at the address of the ipp
variable and find the contents 0x12345680. Which is of course the address where ip1
is stored. We can go to that address, check the contents there, and find the address of i
, and then finally we can go to that address and find the number 5.
So if we take the contents of ipp, *ipp
, we will get the address of the pointer variable ip1
. By writing *ipp=ip2
we copy ip2 into ip1, it is equivalent to ip1=ip2
. In either case we would get
Address Data Meaning
0x12345680 12 34 56 7C // The variable ip1
0x12345684 12 34 56 7C // The variable ip2
(These examples were given for a big endian CPU)
Notice the assignments:
ipp = &ip1;
results ipp
to point to ip1
.
so for ipp
to point to ip2
, we should change in the similar manner,
ipp = &ip2;
which we are clearly not doing. Instead we are changing the value at address pointed by ipp
.
By doing the folowing
*ipp = ip2;
we are just replacing the value stored in ip1
.
ipp = &ip1
, means *ipp = ip1 = &i
,
Now, *ipp = ip2 = &j
.
So, *ipp = ip2
is essentially same as ip1 = ip2
.
ipp = &ip1;
No later assignment has changed the value of ipp
. This is why it still points to ip1
.
What you do with *ipp
, i.e., with ip1
, does not change the fact that ipp
points to ip1
.
My question is: Why in the second picture, ipp is still point to ip1 but not ip2?
you placed nice pictures, I'm going to try to make nice ascii art:
Like @Robert-S-Barnes said in his answer: forget about pointers, and what points to what, but think in terms of memory. Basically, an int*
means that it contains the address of a variable and an int**
contains the address of a variable that contains the address of a variable. Then you can use the pointer's algebra to access the values or the addresses: &foo
means address of foo
, and *foo
means value of the address contained in foo
.
So, as pointers is about dealing with memory, the best way to actually make that "tangible" is to show what the pointers algebra does to the memory.
So, here's your program's memory (simplified for the purpose of the example):
name: i j ip1 ip2 ipp
addr: 0 1 2 3 4
mem : [ | | | | ]
when you do your initial code:
int i = 5, j = 6;
int *ip1 = &i, *ip2 = &j;
here's how your memory looks like:
name: i j ip1 ip2
addr: 0 1 2 3
mem : [ 5| 6| 0| 1]
there you can see ip1
and ip2
gets the addresses of i
and j
and ipp
still does not exists. Don't forget that addresses are simply integers stored with a special type.
Then you declare and defined ipp
such as:
int **ipp = &ip1;
so here's your memory:
name: i j ip1 ip2 ipp
addr: 0 1 2 3 4
mem : [ 5| 6| 0| 1| 2]
and then, you're changing the value pointed by the address stored in ipp
, which is the address stored in ip1
:
*ipp = ip2;
the program's memory is
name: i j ip1 ip2 ipp
addr: 0 1 2 3 4
mem : [ 5| 6| 1| 1| 2]
N.B.: as int*
is a special type, I prefer to always avoid declaring multiple pointers on the same line, as I think the int *x;
or int *x, *y;
notation can be misleading. I prefer to write int* x; int* y;
HTH
Because when you say
*ipp = ip2
you're saying the 'object pointed by ipp
' to point the direction of memory that ip2
is pointing.
You're not saying ipp
to point ip2
.
If you add the dereference operator *
to the pointer, you redirect from the pointer to the pointed-to object.
Examples:
int i = 0;
int *p = &i; // <-- N.B. the pointer declaration also uses the `*`
// it's not the dereference operator in this context
*p; // <-- this expression uses the pointed-to object, that is `i`
p; // <-- this expression uses the pointer object itself, that is `p`
Therefore:
*ipp = ip2; // <-- you change the pointer `ipp` points to, not `ipp` itself
// therefore, `ipp` still points to `ip1` afterwards.
If you'd want ipp
to point to ip2
, you'd have to say ipp = &ip2;
. However, this would leave ip1
still pointing to i
.
Very beginning you set,
ipp = &ip1;
Now dereference it as,
*ipp = *&ip1 // Here *& becomes 1
*ipp = ip1 // Hence proved
Considere each variable represented like this:
type : (name, adress, value)
so your variables should be represented like this
int : ( i , &i , 5 ); ( j , &j , 6); ( k , &k , 5 )
int* : (ip1, &ip1, &i); (ip1, &ip1, &j)
int** : (ipp, &ipp, &ip1)
As the value of ipp
is &ip1
so the inctruction:
*ipp = ip2;
changes the value at the addess &ip1
to the value of ip2
, which means ip1
is changed:
(ip1, &ip1, &i) -> (ip1, &ip1, &j)
But ipp
still:
(ipp, &ipp, &ip1)
So the value of ipp
still &ip1
which means it still points to ip1
.
Because you are changing the pointer of *ipp
. It means
ipp
(varaiable name)----go inside.- inside
ipp
is address ofip1
. - now
*ipp
so go to (adress of inside)ip1
.
Now we are at ip1
. *ipp
(i.e.ip1
) = ip
2.
ip2
contain address of j
.so ip1
content will be replace by contain of ip2(i.e. address of j), WE ARE NOT CHANGING ipp
CONTENT. THAT'S IT.
*ipp = ip2;
implies:
Assign ip2
to the variable pointed to by ipp
. So this is equivalent to:
ip1 = ip2;
If you want the address of ip2
to be stored in ipp
, simply do:
ipp = &ip2;
Now ipp
points to ip2
.
ipp
can hold a value of (i.e point to) a pointer to pointer type object. When you do
ipp = &ip2;
then the ipp
contains the address of the variable (pointer) ip2
, which is (&ip2
) of type pointer to pointer. Now the arrow of ipp
in second pic will point to ip2
.
Wiki says:
The *
operator is a dereference operator operates on pointer variable, and returns an l-value (variable) equivalent to the value at pointer address. This is called dereferencing the pointer.
Applying *
operator on ipp
derefrence it to a l-value of pointer to int
type. The dereferenced l-value *ipp
is of type pointer to int
, it can hold the address of an int
type data. After the statement
ipp = &ip1;
ipp
is holding the address of ip1
and *ipp
is holding the address of (pointing to) i
. You can say that *ipp
is an alias of ip1
. Both **ipp
and *ip1
are alias for i
.
By doing
*ipp = ip2;
*ipp
and ip2
both points to same location but ipp
is still pointing to ip1
.
무엇 *ipp = ip2;
실제로하는 일은 그 사본의 내용이다 ip2
(의 주소 j
에) ip1
(로 *ipp
의 별칭입니다 ip1
효과가), 두 포인터를 만들고 ip1
와 ip2
같은 객체를 가리키는 ( j
).
그래서, 두 번째 그림에서 의 화살표 ip1
와 ip2
가리키는 j
동안 ipp
여전히 가리키는 ip1
더 수정의 값을 변경할 수행되지 않습니다으로ipp
.
참고 URL : https://stackoverflow.com/questions/21604946/pointer-to-pointer-clarification
'programing tip' 카테고리의 다른 글
Python : TypeError : 'str'및 'int'개체를 연결할 수 없습니다. (0) | 2020.06.19 |
---|---|
Mongo DB에서 저장과 삽입의 차이점은 무엇입니까? (0) | 2020.06.19 |
고품질 이미지 스케일링 라이브러리 (0) | 2020.06.19 |
배치 파일을 기다리지 않고 응용 프로그램을 시작하는 방법은 무엇입니까? (0) | 2020.06.19 |
무엇을 ' (0) | 2020.06.18 |