포인터란
포인터에 대해서 제가 아는 만큼 정리를 해보겠습니다.
포인터란? 어떠한 변수의 값들을 저장하는것이 나닌 주소를 저장하는 것을 나타냅니다.
ex) int num = 5;가 되면 변수 num에는 5라는 값이 저장이 됩니다. 그러나 포인터 변수인 *pnum을 쓰게 되면 num의 주소값이 저장이 되게 됩니다.
예시에서 *pnum을 사용하게 되는데 이 것을 포인터 변수라고 부릅니다.
이러한 변수는 int * pnum으로 사용이 됩니다.
-
int * pnum
-
pnum : 포인터 변수의 이름
-
int * : int형 변수의 주소 값을 저장하는 포인트 변수
포인트 변수를 설정할 때 포인터 형 (int *,double *,char *), 포인터 연산자(& , * ) 를 주로 사용합니다.
-
첫번째로는 int,double와 같은 type입니다.
-
char은 1byte, int 인경우는 4byte, double 은 8byte의 주소값을 할당하게 됩니다.
-
int *같은 포인터 변수를 선언하는 경우는 8byte로 설정이 되게 됩니다.
-
이러한 이유는 컴퓨터의 시스템에 따라서 달라지게 되는데요 예로들어 32bit시스템에서는 4byte로 표현되지만 64bit는 8byte로 설정이 됩니다.
-
-
두번째로는 & 연산자를 사용하는데요
-
&연산자의 의미는 변수의 주소값을 반환하는 연산자 입니다.
-
ex) int num = 4로 선언을 하였을때 &num은 num변수의 주소값이 나타나게 됩니다.
-
&연산자의 피연산자 num와 같은 변수이어야 하고 상수는 피연산자가 될수가 없습니다.
-
-
세번째로는 * 연산자를 입니다.
-
*연산자는 포인터가 가리키는 메모리 공간에 접근할때 사용하는 연산자입니다.
-
ex) int num = 19; int * pnum=# 선언을 했을때 *pnum은 num의 메모리값인 19가 나오게 됩니다.
- 추가적으로 이러한 포인터 변수를 선언할 때 쓰레기값이 있기 때문에 초기화 과정을 거쳐야됩니다.
-
이 과정에서 NULL포인터를 사용합니다.
int * ptr1 = 0;
int * ptr2 = NULL; // 아무것도 가리키지 않는다는 뜻을 나타냅니다.
총 이러한 연산자와 형(type)을 사용하게 되면 이렇게 되는데요 밑의 사진과 같은 결과가 나오게 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 |
#include <stdio.h>
int main (void)
{
int num1 = 100, num2 = 100;
int * pnum=NULL;
pnum = &num1;
(*pnum)+=30;
pnum = &num2;
(*pnum)-=30;
printf("num1:%d, num2;%d \n",num1,num2);
} |
cs |
포인터와 배열의 관계
배열도 포인터 변수로서 사용이 됩니다.
이러한 배열의 포인터는 값을 바꿀수가 없는 상수 형태의 포인터 즉 '포인터 상수'라고 불립니다.
왜냐하면 배열의 첫번째 byte의 주소값이 배열의 이름을 출력한 결과이기 때문입니다.
배열의 첫번째 주소값 = 배열의 이름 = 포인터 상수
그렇다면 포인터 변수와 배열의 이름의 차이가 어떻게 될까요?
|
포인터 변수 |
배열의 이름 |
이름이 존재하는가? |
존재 |
존재 |
무엇을 나타내거나 저장하는가 ? |
메모리 주소값 |
메모리의 주소값 |
변수인가? 상수인가? |
변수 |
상수 |
- 결국에는 주소값을 변경할수 있는가에 차이가 있습니다.
- 이것을 통해서 변수인가 상수인가에대해서 나눌수가 있습니다.
- 추가적으로 배열인 경우는 배열의 첫부분이 포인트임으로 &연산자를 붙여주지 않습니다.
포인터연산
포인터에서는 연산이 가능한데요
int * ptr1;의 주소가 0000라고 햇을때 ptr1 ++를 해주면 int형만큼 증가하기 때문에 0004가 됩니다.
따라서 int형 포인터를 대상으로 n증가 = n x sizeof(int)크기만큼 증가
doble형 포인터를 대상으로 n증가 = n x sizeof(double)크기 만큼 증가
결국 TYPE형 포인터를 대상으로 n의 크기만큼 값을 증가 및 감소 시, n x sizeof(TYPE)의 크기만큼 주소값이 증가,감소
결국 arr[i] = *(arr+i) 입니다.
int arr[3] = {11,22,33}
int * ptr = arr;
printf("%d,%d,%d \n", *ptr , *(ptr+1), *(ptr +2));
출력값은 11,22,33이 됩니다.
문자열포인터
포인터를 이용하여 문자열을 선언하는 방식이 있습니다.
기존에는 배열을 이용하는 방식과 포인터 변수를 사용하여 선언하는 방식이있습니다.
- char str[] = "My string"; // 배열을 사용
- char *str2 ="Your String"; //포인터를 사용
- 배열을 이용하면 문자열의 일부를 변경이 가능하므로 변수 형태의 문자열입니다.
- 반면에 포인터를 이용하여 문자열을 선언을 하면 변경이 불가능하므로 상수 형태의 문자열입니다.
- 이러한 두 방법의 차이는 str1은 문자열 전체를 저장하는 배열이고 str2는 단순히 첫번째 문자를 가리키고 있습니다.
- 결국 포인터를 이용하게 되면 다른 다른 문자열을 변경이 가능하다는 점이 있습니다. ex)다른 문자열 지정가능
- 또한 배열을 이용하면 문자열 내부의 값이 바뀔수 있는 점이있습니다. ex) str에 있는 문자 하나 변경가능
포인터 배열
이러한 포인터들을 배열로써도 만들수가 있습니다.
이를 주소값의 저장이 가능한 배열을 가르켜 '포인터 배열'이라고 합니다.
이 배열은 char * strArr[3]; 처럼 선언해주면 됩니다.
이경우 각 배열의 구간 마다 포인터가 생성이 되게 됩니다.
예로들었던 char *strArr[3] = {0x0003,0x0048,0x2101}처럼 선언되어집니다.
포인터와함수
기본적으로 함수에서는 인자의 전달 & 반환의 기능이 있습니다.
요기서 인자 전달의 기본 방식은 복사입니다. 즉 함수호출시 전달되는 인자의 값은 매개변수에 복사가 됩니다.
- 예로들어 int simple(int num);함수를 선언하고
- 메인 함수에 int age = 17; 선언과 simple(age);함수를 호출하게 되면
- age의 값이 num에 복사가 됩니다.
하지만 이러한 값은 변수 age와 num은 관련이 없으므로 simple함수에서 num의 값을 변화를 주어도 age에서는 변화가 없습니다.
함수를 통하여서 변수 age를 변경시키기 위해서는 이상적으로는 함수를 통째로 옮길수는 없으므로
포인터를 사용하여서 변수에 변화를 줍니다. (예로들면 아파트를 통째로 못옮기니 주소를 가르쳐주는 방법이죠)
이러한 방법에 대해서 코딩을 통해 예시를 들면
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 |
#include <stdio.h>
void ShowArr(int * param, int len) //포인터를 사용하여 주소값을
{
int i;
for (i = 0; i < len; i++)
printf("%d", param[i]);
printf("\n");
}
int main(void)
{
int arr1[3] = { 1,2,3 };
int arr2[5] = { 4,5,6,7 };
ShowArr(arr1, sizeof(arr1) / sizeof(int));
ShowArr(arr2, sizeof(arr2) / sizeof(int));
} |
cs |
이렇게 됩니다. 이것을 통해서 배열의 주소값을 알면 언제든지 배열에 접속이 가능합니다.
추가적으로 함수 *param 은 param[]으로 사용도 가능하다.
- 포인트를 통해서 함수를 호출하는 방식을 Call-by-reference라고 불립니다.
- 반대로 변수를 통해서 함수를 호출하는 방식을 call-by-value라고 불립니다.
이것을 통해서 scanf에서 &연산자를 사용하는 이유를 알수가 있습니다.
결국 내가 입력한 변수의 주소를 입력해야 변수에 데이터를 입력이 가능함으로 &연산자가 붙게 됩니다.
추가적으로 포인트 변수에서도 const함수가 붙을수 있습니다
이 함수를 추가하게 되어지면 포인트 변수가 상수로 바뀌게 됩니다.
- const는 어디게 붙느냐에 따라서 달라집니다.
- 예로들면 int *const ptr = & num1;
- ptr = & num2; //컴파일 에러
- *ptr = 40; //컴파일 성공
- 이부분에서는 const를 사용하면 한번 가리키기 시작한 변수는 끝까지 가리켜야되는겁니다. 하지만 변수안에 데이터값은 바꿀수가 있습니다.
'공부 > C언어 ' 카테고리의 다른 글
문자와 문자열에 관련된 함수 (0) | 2017.01.26 |
---|