프로그래밍 언어에서 

타입

타입이 가질 수 있는 집합 + 타입에 수행 가능한 연산 

으로 구성됨


예를 들어 C에서

int 타입은 

–2,147,483,648 ~ 2,147,483,647 의 정수형의 집합을 가지고(32비트)

+ - * / 등의 연산을 할 수 있음


근데 사용자가 struct로 정의한 타입은

* 곱하기를 못 쓰잖음?


포인터도 곱하기 못쓰고

더하기 빼기 연산도 좀 다르잖음?


이렇게 프로그래밍 언어에서는 타입마다 쓸 수 있는 연산다름.



그런 식으로 생각하면

포인터는 64비트의 정수형 집합을 가지고

+ - ++ -- 등의 연산에 더해서

(위 연산들도 일반적인 정수 더하기와는 다르고)

역참조 * 연산(dereference)을 할 수 있다는 거임


그냥 그게 끝임..


int* ptr;

int** ptr;

int****** ptr;


뭘 어떻게 선언하든 하는 짓은 다 똑같음

그냥 64비트 정수를 저장할 수 있고

그 정수에 대한 연산이 독특한 것 뿐임


포인터가 뭐를 가리키네 그딴 거 다 집어치우고...


포인터에는 걍 64비트 정수가 저장되고

*ptr 역참조를 하게되면 64비트 정수를 주소값으로 해석해서 변수처럼 쓰는 거임



한줄요약: 포인터는 독특한 연산(역참조)을 가진 정수형 타입이다



그럼 역참조 연산은 무엇인가?

일단 설명하자면 

포인터형 변수에 들어 있는 64비트 정수를 주소로 해석해서 거기 접근하는 거임

말로는 어렵고..

예를 들면서 설명해보겠음


int num = 0;

int* ptr = # //모든 변수는 주소값을 갖는다

void side_effect(int* pnum){

    int x = *pnum;

    *pnum = 99;

}


이렇게 선언하면 이후

*ptr = 12;     하면 num의 값이 바뀌고

int a = *ptr;  하면 a에 num의 값이 들어갈 수 있음


side_effect 함수 내부에서도 동일한 일이 일어남

int x = *pnum; 이렇게 하면 num의 값을 x에 넣는 거고

*pnum = 99;    이렇게 하면 또 num의 값이 바뀜.


여기서 역참조의 정체를 대강 파악 가능함

역참조를 쓰면 스코프에 상관없이 변수에 접근할 수 있다는 거임


이렇게 생각해보셈. *ptr이랑 *pnum 대신에 int형 변수 num을 갖다 놓는 거야

스코프 그딴 건 다 무시해 버리고.


void side_effect(int* pnum){

    int x = *pnum;

    *pnum = 99;

}


int main(void){

    int num = 0;

    int* ptr = # 


    *ptr = 12;

    int a = *ptr;

    return 0;

}


이렇게 되어 있으면

역참조를 한 부분은 이렇게 되는 거라고 생각해 보셈


void side_effect(int* pnum){

    int x = num;

    num = 99;

}


int main(void){

    int num = 0;

    int* ptr = # 


    num = 12;

    int a = num;


    side_effect(&num);

    return 0;

}


그럼 쉽져? 이게 역참조라고 생각하면 됨

여기서 중요한 건 지역변수함수에서 접근해서 변경할 수 있다는 거임


포인터가 없으면 뭔 짓을 해도 지역변수를 함수에서 변경할 수 없음

절대 불가능함 ㅋ

물론 전역 변수를 쓸 순 있겠지만 그건 존나 쳐맞을 짓임



뇌피셜 요약: 역참조 *ptr는 전에 넣어둔 주소의 변수를 대신 쓰는 것처럼 생각할 수도 있다

뇌피셜임 ㅎㅎ;



그럼 이중포인터의 예를 또 볼까용

void side_effect(int* pnum){

    int x = *pnum;

    *pnum = 99;

}


int main(void){

    int x = 0

    int* px = &x;

    int** ptr = &px; 


    *ptr = 12;

    int a = *ptr;

    return 0;

}


위에서 취소선 그은 애들은 컴파일이 안 될겁니다.

왜 안될까?

아까처럼 생각해 볼까용?


int main(void){

    int x = 0

    int* px = &x;

    int** ptr = &px; 


    px = 12;

    int a = px;

    return 0;

}


이렇게 보면 왜 안 되는지 쉽게 알 수 있다

지금 주소값을 ㅈ대로 int형 값 12로 넣으려고 하는데

만약 주소가 12인 곳을 역참조하면 어떻게 될까? 후로그램이 뒤진다

그래서 컴파일러가 int형을 int* px의 변수에 대입하는 걸 금지한다.


이제 두번하면 어떻게 되나..


int main(void){

    int x = 0

    int* px = &x;

    int** ptr = &px; 


    **ptr = 12;

    int a = **ptr;

    return 0;

}


그럼 요건 이렇게 되겠지

int main(void){

    int x = 0

    int* px = &x;

    int** ptr = &px; 


    *px = 12;

    int a = *px;

    return 0;

}


int main(void){

    int x = 0

    int* px = &x;

    int** ptr = &px; 


    num = 12;

    int a = num;

    return 0;

}


이건 말이 된다. 

int 변수에 int 값을 넣는다

그리고 int a를 int형 변수의 값으로 초기화한다

말 되네!



사실 제 머가리 속에서는 이렇게까지는 안 하고

C에서는 좌측값은 그냥 주소라고 생각합니다

우측값이구요





http://blog.naver.com/rhdnfka94/221046491976




3줄 요약

프로그래밍 언어에서 타입은 값의 집합 + 타입에 수행 가능한 연산 으로 정의된다.

포인터는 역참조라는 독특한 연산을 가진 정수형 타입이다.

(뇌피셜)역참조 *ptr 는 포인터에 넣어둔 주소의 변수를 대체하는 것으로 이해할 수 있다.