Language/C C++

[C] Pointer 개념정리

nineil91 2021. 2. 3. 18:36

포인터의 기본 개념

포인터는 변수의 주소값을 받아서 사용한다. 입력받을때 버퍼 메모리를 굳이 거치지 않고 직접 해당 변수로 접근하도록 한다.

 

메모리의 저장방식

PC에서 저장공간은 Ram memory와 Hard Disk Drive가 있다. 줄여서 RAM과 HDD라 칭하겠다. 둘의 기본 구조는 같고 단기 기억 장치(휘발성) 이나 장기 기억 장치(비휘발성)으로 나뉘는데 자세한건 컴퓨터 아키텍처 정리에서 다루기로 하고 C언어에서 메모리는 RAM에 할당된다는 것을 알아두면 된다.

 

RAM의 데이터 저장 구조는 다음과 같다.

              ←1byte
               
               
               
               
               
               
               
               
               

한줄에 8칸인 저장 구조가 아래로 쭉 나열되어있는 것이다. 위에서 표시한 10칸보다 훨씬 많을 것이다. 한줄에 8칸이 할당되어 있으니 1byte가 기록될 수 있는 셈이다. 아래 설명부터는 8칸을 한칸으로 하고 1바이트씩 묶어 설명함을 알아주길 바란다. 1바이트에 해당하는 한칸에 주소 하나씩 배정이 된다. 메모리 공간을 그려보면 다음과 같다.

 

 

 

보통 주소값이 0부터 하여 낮은 곳에는 시스템 프로그램 그 위에 OS가 배치되기 때문에 주소값을 임의로 잡으면 걷잡을 수 없이 컴퓨터가 꼬일 수 있으므로 주의하자. 보통 변수를 임의배정해두고 주소값이 뭔지 궁금해서 printf("%d", &a); 해보면 1823874881273 뭐 이런 숫자가 나온다. 당신이 혹시 컴퓨터가 나사 빠진 것 처럼 돌아가는 것을 보길 원한다면 (나사 빠진 것 처럼 돌아가기라도 하면 다행이다. 이때는 컴퓨터에 있는 파일을 복원하고 밀어버리면 된다. 하지만 대부분 컴퓨터가 갑자기 나갈것이다. A/S 센터에 돈을 쓰고 싶거나 보증기간 내에 어떻게든 본전을 뽑고 싶지 않다면 말리겠다.) 해보길 바란다. 

 

 

 

 

주소 연산자 : &

#include <stdio.h>

int main(void)
{
	int a;
    double b;
    char c;
    
    printf("%u", &a); //~~~00
    printf("%u", &b); //~~~04
    printf("%u", &c); //~~~05
    
    return 0;
}

주석처리 하고 달아둔 것이 주소값 예시이다. int형은 4바이트를 차지하고 나머지는 대부분 1바이트를 차지한다. 여기서 %u는 부호없는 10진수를 출력할때 사용하는 C언어 출력타입이다. 주소는 0부터 시작해 음수가 없으므로 %u 변환 문자를 사용하는 것이 좋다.

 

더하여) 메모리 주소의 출력 변환 문자

printf("%p", &a);

주소는 보통 16진수로 표기한다. 때문에 주소를 출력할때는 전용 변환 문자인 %p를 사용하길 권장한다.

 

포인터와 간접 참조 연산자 : *

#incldue <stdio.h>

int main(void)
{
	int a;
    int *pa;
    
    pa = &a;
    *pa = 10;
    
    printf("%d", *pa); //10
    printf("%d", a); //10
    
    return 0;
 }

마찬가지로 주석처리 해둔것이 출력값이다. 왜 이렇게 나오는가? 위의 코드를 보면 a를 정수형 변수로 선언하고 pa를 정수형 포인트 변수로 선언한다. 그리고 pa에 a의 주소값을 대입했고 *pa를 하여 pa에 저장된 주소값이 가르키는 변수에 10을 넣었다. 결론적으로는 a와 a를 출력한 셈이다. pa를 출력한다면 아마 주소값이 뜰거다. 아래와 같이 확인 할 수 있다.

const를 사용한 포인터

+) 포인터 변수로 여러번 넘겨받을때도 보안해제를 써주는게 출력이 잘 될 것 이다. 호환이 안되는 경우가 많다.

 

const를 포인터 변수 선언 앞에 붙이면 포인터 변수 pa의 값이 변수 a의 주소값으로 고정되어 항상 *pa를 출력하면 변수 a의 데이터 값을 출력한다. 

 

포인터 완전 정복을 위한 포인터 이해하기

ps. 주소는 상수이고 포인터는 변수이다. 

 

주소와 포인터의 크기

포인터 변수는 상수 즉, 주소값을 가리키므로 크기를 4 차지한다.

 

포인터의 대입 규칙

포인터는 가리키는 변수의 형태가 같을때만 대입해야 합니다.

컴파일러는 p에 저장된 값을 int형 변수의 주소로 생각하고, pd에 저장된 값을 double형 변수의 주소로 생각한다. pd에 p를 대입한 후 간접 참조 연산을 수행하면 변수 a에 할당된 영역 이후의 할당되지 않은 영역까지 사용하게 된다.

포인터를 사용하는 이유

임베디드 프로그래밍에서 메모리에 직접 접근하거나 동적 할당된 메모리를 사용하는 경우에 포인터가 필요하다.

 

두 변수의 값을 바꾸는 문제

포인터 ver.

no 포인터 ver.

함수 호출을 1회만 하면 실패한다. 그렇다면 이것을 어떻게 해결하는게 좋은가?

바로 프린트 해버리면 안되나? 답은 맞는데