본문 바로가기

프로그래밍기초

C,C++언어 생기초 C언어의 꽃 포인터 시작하기

C,C++

C언어의 핵심인 꽃, 포인터

포인터는 C언어가 고급언어인데오 low 레벨 언어의 특성을 지닌다고 이야기하게 만든 장본인입니다.

포인터가 왜중요하냐? 바로 메모리를 직접적으로 접근하고 제어할 수 있게 해주기 때문입니다

이렇게 컴퓨터의 하드웨어에 접근하는 특성 때문에 게임같이 메모리나 성능이 중요한 프로그램들이

C나 C++로 만들어집니다

이 외에도 운영체제단처럼 직접적으로 하드웨어와 소통해야 하는 프로그램은 대부분이 전~ 부 C로

만들어져 있어요

 

자바를 먼저 접한 사람은, 자바에는 포인터라는 것이 없던데 쓸 모 없는 것이냐 할 수도 있지만 

자바 언어 기반이 C언어예요 결국 내부적으로 C가 다 포인터를 이용해서 처리해줬기 때문에

보이지 않았을 뿐입니다.

 

1. 메모리 주소

포인터란 결국 메모리 주소와 연관 된 문법이예요.

이를 이해하기 위해 먼저, 우리가 데이터를 저장하면 메모리에

어떻게 저장이 되는지 알고 넘어갑시다.

 

 

'n이라는 이름을 가진 박스에다가 10을 저장했다'

라는 말은 곧 10을 메모리 어딘가에다가 저장하고 우리가 쉽게 쓸 수 있게

n이라는 이름을 붙인겁니다. 그림을 보면 아래와 같습니다.

메모리 위치는 같은 코드라도 작성할 때마다 바껴요. (휘발성 메모리이기 때문이죠)

00120B14라는 메모리 주소에 int 크기 즉 4byte만큼 공간을 잡고

그 공간에 10이라는 값을 넣어줬네요 (항상 C언어는 메모리 시작번지만 가지고 위치를 표현하고

거기서부터 자료형의 크기만큼 공간을 할당합니다-> 즉 위치 찾는 기준은 시작위치+거기서부터 떨어진 간격 offset)

실수도 마찬가지로 double크기인 8byte만큼 공간을 잡은 다음에, 3.141592 값을 넣고 d라고 이름을 붙여줬어요.

n, d 이런 이름을 통해 우리가 복잡한 메모리 주소(00120B14이런거)를 기억하지 않아도 쉽게 호출할 수 있는거죠!

 

2. &연산자, 포인터란? 포인터의 쓰임.

그런데 우리는 가끔 메모리 주소를 알아야 할 때가 있어요. 참고로 눈치챘겠지만

메모리 주소값을 저장할 수 있는 자료형이 포인터입니다! 포인터도 int(정수를 저장하는 자료형),

char(문자를 저장하는 자료형)처럼 결국 하나의 자료형이예요.

포인터가 언제 필요하냐? 예를 들어 우리가 함수를 작성했다고 생각해봅시다

 

이렇게 add라는 함수를 정의해줬어요.

근데 그 함수 매개변수에다가 값을 줘서 안에서 아무리 더해도 원래 값에 영향을 미치지 못해요

즉 11라인 add(a,b,sum)에 3의 값을 저장하고 있는 a와 4를 저장하고 있는

b값을 전달해서 3+4인 7을 sum에 저장하는게 목적이었는데 실제로 출력 값은 0입니다

왜냐?실제 sum의 주소 값이 매개변수로 대입되는 것이 아니기 때문이죠.

저렇게 할 경우 add라는 함수는 다른 주소에다가 sum이라는 똑같은 이름을

가진 공간을 만들고 거기에 저장합니다. 즉 10번 라인에 초기화된 sum과 3번 라인 sum은 다른 애라는거

즉 같은 공간이 아니니 아무리 더해도 기존의 sum에는 영향을 못미치는 겁니다.

 

 

여기서 변수명 앞에 &를 붙여주면 실제 잡힌 메모리 위치를 보여줍니다.

일반적으로 &연산자와 *연산자를 포인터 연산자라고 합니다.

'scanf("%d", &a);' 많이 썼던 출력 함수죠? 여기 &도 결국 주소를 의미합니다.

a라는 변수의 주소에다가 값을 받아서 저장시켜달라는거죠~

아무튼 저 코드의 실제 출력 값을 확인해보면

주소가 달라요!! 정확한 메모리 위치 값은 신경쓰지 않아도 됩니다.

어차피 프로그램 껐다 키면 또 바껴있을 값이예요. 여기서 핵심은 같은 sum인데도 위치가 다르게 잡힌다는거죠!

그럼 기존의 sum의 값을 변경시키려면 어떻게 해야할까요?

바로 매개변수에 sum이 저장되어 있는 주소를 직접적으로 알려주는거예요.

그러면 그 주소로 가서 값을 바꾸니까 변경이 적용되겠죠! 이것은 포인터가 쓰이는 한 예일 뿐입니다.

포인터 특성상 주소 값을 저장할 수 있기 때문에 실제 값이 담긴 변수명을 몰라도 접근할 수 있어요

이렇게 다른 변수의 주소를 직접적으로 가리켜 변수명 없이도 접근하는데 사용하기도 합니다.

실제로 포인터는 다양한 상황에서 유용하게 또 필수적으로 쓰여요! 앞으로 많이 만나게 될 친구입니다

 

3. 포인터 문법.

 

1. 선언할 때!, 주소 값을 저장하는 할 때 => 포인터 변수를 선언할 때는

데이터형을 먼저 쓰고, *를 쓴 다음, 변수명을 적어줍니다. 곱하기할 때 쓰는

*랑 모양은 같지만 *연산자와는 다릅니다! 즉 *는 문법에 따라 쓰임새가 달라지죠

 

 

포인터 변수를 선언할 때 데이터형과 *를 함께 써주는데 *기호가 해당 변수를 포인터로 만듭니다.

char*는 char형 변수의 주소,

int*은 int형 변수의 주소,

double*은 double형 변수의 주소! 알겠죠?

'int* a;'이든 'int * a'이든 'int *a' 이든 상관없어요.

하지만 여기서 다른점은 자료형의 역할입니다.

 

 

 

double a;하면 자료형은 8바이트를 메모리상에 만들어놓는 역할을 해요.

근데 포인터의 경우 double* a;했을 때 8바이트를 만들라는 뜻으로

double이 있는 것이 아닙니다. 어차피 주소값은 정수이므로 타입(int)이 일정하기 때문이죠.

즉 포인터 변수의 크기는 포인터 변수가 가리키는 변수의 데이터형에 관계없이 항상 같습니다. (항상 4바이트)

여기서 포인터의 자료형은! 포인터 타입이 아닌, 포인터 변수가 가리키는 변수의 타입을 말해요

그래야 그 주소값을 찾아갔을 때 내가 얼만큼의 크기를 읽어들여야 하는지 알 수 있으니까요

 

 

실수 num의 주소 값을 numAddress라는 포인터 변수에다가 저장해줬습니다.

출력값은 numAddress의 크기는 4가 되고(7번 라인)

(8번 라인) numAddress가 가리키는 num 공간의 크기는 double이므로 출력은 8이 됩니다. ('cout<<sizeof(*numAddress);'와 같은 말)

선언시 주의 사항은?

'int a, b;' 는 결국 'int a; int b;'랑 같아서 포인터도 한 번에 이어쓰려고 6라인처럼 쓰는 사람들이 있는데,

정확히는 7라인처럼 써줘야 'int*e; int*f;'로 적용됩니다. 6라인은 c는 포인터 변수, d는 int 변수가 돼요.

2. 호출할 때! 주소 값으로 찾아가 그 안에 있는 값을 확인할 때!

*의 쓰임법은 선언할 때 말고 호출할 때도 사용됩니다. 자료형 없이 '

* 포인터변수명' 하면 포인터변수에 저장되어 있는 주소로 찾아가

그 주소가 가지고 있는 실제 값을 가리킵니다.

 

 

 

 

*numAddress 호출을 하면 numAddress에

저장되어 있는 주소 값 00B3FA00을 찾아가서

그 안에 저장된 값 3.1415를 가져오는 것을 볼 수 있어요.

이를 상자에 빗대어 그림으로 표현해봤어요!

나중에 이중 포인터, 삼중 포인터

하다보면 머리가 혼돈이되니

개념을 단단히 잡아놓는게 좋습니다.

 

 

4. 포인터 사용시 주의사항

 

포인터는 선언과 초기화를 같이 하면 좋지만 때에 따라 따로 해줘야 할 때가 있는데요.

 

3줄처럼 포인터 변수를 선언만 하고 초기화하지 않으면,

포인터 변수는 쓰레기 값으로 초기화 돼요. 이런 상태에서 * 연산을 통해서 100을 저장하는

것은 치명적인 결과로 이어질 수 있습니다. ptr이 가리키는 위치를 모르니까요!

(정말 중요한 곳이라면 운영체제가 차단하긴 하지만..ㅎㅎ)

따라서 나중에 주소값을 저장할 예정이라면

'int * ptr;'보다는 'int * ptr = NULL;'을 해주는 것이 바람직합니다.

하지만 NULL로 초기화 해놓고 나중에 주소로 대입하는걸 해준줄 알고 착각해

연산을 해버리면 메모리 참조가 잘못되었다는 에러 메세지를 많이 접하게 될 겁니다.ㅎ.ㅎㅎ

NULL로 초기화 하고 꼭 나중에 매칭 잘 시켜준 후 연산하기!

포인터와 배열은 엄청 긴밀한 관계를 갖고 있어요. 다음시간에 이에 대해 살펴볼게요

뿅~

 

#C언어

#포인터

#포인터개념

#포인터기초

#C언어메모리

#프로그래밍기초

#포인터문법

#엔퍼센트주소