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++, Java 등 언어 공통] 반복문 상세설명 for, do while, 향상된 for문 사용법, 차이점 및 실행 순서 (0) | 2019.05.24 |
---|---|
프로그래밍C++, java 생기초) 연산자 개념정리 미치 활용, 실습예제 (0) | 2019.05.24 |
C/C++ 프로그램 구조 개발 처음시작하기 (0) | 2019.05.22 |
프로그래밍 기초) 함수란? 함수의 종류, 함수 역할 및 기능, 메인함수 (0) | 2019.05.21 |
C, C++, java 등 언어 공통 반복문 상세설명!! (0) | 2019.05.19 |