KUR Creative


포인터는 그냥 정수형 타입의 일종일 뿐이얏

타입의 정의와 포인터 타입

프로그래밍 언어에서 
타입
타입이 가질 수 있는  의  집합  + 타입에 수행 가능한  연산  
으로 구성됨

예를 들어 C에서
int 타입은 
–2,147,483,648 ~ 2,147,483,647 의 정수형의 집합을 가지고(32비트)
+ - * / 등의 연산을 할 수 있음

근데 사용자가 struct로 정의한 타입은
* 곱하기를 못 쓰잖음?

포인터도 곱하기 못쓰고
더하기 빼기 연산도 좀 다르잖음?

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


그런 식으로 생각하면
포인터는 64비트의 정수형 집합을 가지고
+ - ++ -- 등의 연산에 더해서
(위 연산들도 일반적인 정수 더하기와는 다르고)
역참조 * 연산(dereference)을 할 수 있다는 거임

그냥 그게 끝임..

int* ptr;
int** ptr;
int****** ptr;

뭘 어떻게 선언하든  하는 짓은 다 똑같음
그냥 64비트 정수를 저장할 수 있고
그 정수에 대한 연산이 독특한 것 뿐임

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

포인터에는 걍 64비트 정수가 저장되고
*ptr 역참조를 하게되면 64비트 정수를  주소값으로 해석해서 변수처럼  쓰는 거임

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

역참조(dereference) 연산

그럼 역참조 연산은 무엇인가?
일단 설명하자면 
포인터형 변수에 들어 있는 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; 

    x = 12;
    int a = x;
    return 0;
}

이건 말이 된다. 
int 변수에 int 값을 넣는다
그리고 int a에 int형 변수의 값을 초기화한다
말 되네!

사실 제 머가리 속에서는 이렇게까지는 안 하고
C에서는  좌측값은 그냥  주소라고 생각합니다
우측값은  이구요

3줄 요약

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

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

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


과거 블로그 댓글
깃허브 갤러리 댓글
프로그래밍 갤러리 댓글

#from/old-blog#lang/c#concept-lecture개념특강
kur1702090019Archivekur1909300908