[c] 포인터 설명을 가리키는 포인터

나는 이것을 따르고 있었다 포인터에 대한 포인터의 작동 방식에 대한 자습서 를 .

관련 구절을 인용하겠습니다.


    int i = 5, j = 6, k = 7;
    int *ip1 = &i, *ip2 = &j;

이제 우리는 설정할 수 있습니다

    int **ipp = &ip1;

ipp포인트 ip1에있는 점 i. *ipp이다 ip1, 그리고 **ipp이다i 또는 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;


답변

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, ip2ipp. 그런 다음에 할당하면 *ipp“할당”과 같은 의미 ip1입니다. ipp두 번째로 할당 하지 않았으므로 변경되지 않았습니다!

변경 ipp하고 싶다면 실제로 다음을 할당해야합니다 ipp.

ipp = &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);
}

출력 :

여기에 이미지 설명을 입력하십시오


답변

저의 개인적인 견해는 화살표가이 방법을 가리 키거나 포인터를 이해하기 어렵게 만드는 그림입니다. 그것들을 추상적이고 신비한 존재처럼 보이게합니다. 그들은 아닙니다.

컴퓨터의 다른 모든 것과 마찬가지로 포인터는 숫자입니다. 입니다. “포인터”라는 이름은 “주소를 포함하는 변수”라는 멋진 표현입니다.

따라서 컴퓨터가 실제로 어떻게 작동하는지 설명함으로써 주변 환경을 자극하겠습니다.

우리는 int이름 i과 값 5를가집니다. 이것은 메모리에 저장됩니다. 메모리에 저장된 모든 것과 마찬가지로 주소가 필요하거나 찾을 수 없습니다. 말은 수 있습니다 i주소 0x12345678에 끝과 그 친구 j그냥 후 6 개 끝을 값. int가 4 바이트이고 포인터가 4 바이트 인 32 비트 CPU를 가정하면 변수는 다음과 같이 실제 메모리에 저장됩니다.

Address     Data           Meaning
0x12345678  00 00 00 05    // The variable i
0x1234567C  00 00 00 06    // The variable j

이제 우리는이 변수들을 지적하려고합니다. int int* ip1, 및 하나에 대한 하나의 포인터를 만듭니다 int* ip2. 컴퓨터의 모든 것과 마찬가지로 이러한 포인터 변수도 메모리 어딘가에 할당됩니다. 이들이 메모리 바로 다음에 인접한 주소에서 끝나는 것으로 가정하자 j. 이전에 할당 된 변수 ip1=&i;의 주소 ( “i의 주소를 ip1로 복사”)와를 포함하도록 포인터를 설정했습니다 ip2=&j. 줄 사이에 일어나는 일은 다음과 같습니다.

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)

우리가 얻은 것은 아직 숫자를 포함하는 4 바이트의 메모리 덩어리였습니다. 보이지 않는 곳에 신비로운 마법 화살이 없습니다.

실제로 메모리 덤프를 살펴보면 주소 0x12345680에 int또는int* . 차이점은 프로그램이이 주소에 저장된 내용을 사용하도록 선택하는 방법입니다. (우리 프로그램의 임무는 실제로 CPU 에게이 숫자로 무엇을 해야하는지 알려주는 것입니다.)

그런 다음을 사용하여 또 다른 수준의 간접 성을 추가 int** ipp = &ip1;합니다. 다시, 우리는 단지 메모리 덩어리를 얻습니다.

Address     Data           Meaning
0x12345688  12 34 56 80    // The variable ipp

패턴이 익숙한 것 같습니다. 숫자를 포함하는 4 바이트의 또 다른 청크.

위의 가상의 작은 RAM의 메모리 덤프가 있으면 이러한 포인터가 가리키는 위치를 수동으로 확인할 수 있습니다. ipp변수 의 주소에 저장된 내용을 들여다 보고 내용을 0x12345680으로 찾습니다. 물론 주소 ip1가 저장 되는 주소 입니다. 그 주소로 가서 내용을 확인하고 주소를 찾을 수 있습니다.i 다음 해당 주소로 이동하여 숫자 5를 찾을 수 있습니다.

따라서 ipp의 내용을 취 *ipp하면 포인터 변수의 주소를 얻게됩니다 ip1. *ipp=ip2우리는 ip2를 ip1에 복사하여 쓰는 것과 동일합니다 ip1=ip2. 두 경우 모두

Address     Data           Meaning
0x12345680  12 34 56 7C    // The variable ip1
0x12345684  12 34 56 7C    // The variable ip2

(이 예제는 빅 엔디안 CPU에 제공되었습니다)


답변

과제를 확인하십시오.

ipp = &ip1;

결과 ipp를 가리 킵니다 ip1.

정도 ipp점하기 위해 ip2, 우리는 유사한 방식으로 변경해야합니다,

ipp = &ip2;

우리는 분명히하지 않습니다. 대신로 지정된 주소 에서 값을 변경하고 ipp있습니다.
다음을 수행함으로써

*ipp = ip2;

에 저장된 값을 바꾸고 ip1있습니다.

ipp = &ip1, 의미합니다 *ipp = ip1 = &i,
지금,*ipp = ip2 = &j .
따라서 *ipp = ip2본질적으로와 동일합니다 ip1 = ip2.


답변

ipp = &ip1;

더 이상 할당이의 값을 변경하지 않았습니다 ipp. 이것이 여전히을 가리키는 이유 ip1입니다.

*ipp, 즉 으로하는 일이을 가리키는 ip1사실을 변경하지는 않습니다 .ippip1