티스토리 뷰
1) 목표
- 포인터 개념 이해하기
- 이번 강의에서는 포인터의 기본 개념을 배우고 계속되는 강의에서 자세히 다루겠습니다.
2) 설명
▶ 포인터는 c언어에서 제공하는 타입중 하나입니다.
다른 타입과 다르게 포인터 변수는 그값을 주소(어드레스)를 가진다는점이 다릅니다.
// 포인터 변수 선언
char *ptr;
// 포인터 변수에 값을 할당
char sbuf[6];
char *ptr;
ptr = sbuf;
int nVal;
int *nPtr;
nPtr = &nVal;
▶ 포인터 변수는 변수명 앞에 * 를 붙여서 선언합니다.
포인터 타입은 앞에서 살펴본 타입으로 선언 가능합니다.
char *ptr, int *ptr, long *ptr, double *ptr ...
포인터 변수의 타입은 대상이 되는 변수의 타입과 일치해야겠지요.
char에 대한 포인터는 char *, int는 int * ...
▶ 변수가 선언이 되면 메모리가 할당된다고 말씀을 드렸는데 이렇게 메모리가 할당이 되면 메모리의 주소를 갖게 됩니다. 바로 이런 주소를 다루는 변수가 포인터입니다.
▶ char sbuf[6]; 이렇게 선언이 되면 메모리에 6바이트(char가 1바이트, 배열크기가 6)가 할당됩니다.
char *ptr; 포인터 변수가 선언되면 이 변수도 메모리에 8바이트(포인터크기)가 할당됩니다.
sbuf가 메모리에 할당된 주소를 포인터 변수에 대입해서 사용합니다.
ptr = sbuf; sbuf에 할당된 메모리 주소를 ptr변수에 대입합니다.
※ 포인터 변수는 단독(버퍼 없이)으로 사용할 수 없습니다.
포인터 변수는 반드시 어떤 메모리의 주소를 할당(값)해서 사용됩니다. (ptr = sbuf 처럼)
이처럼 어떤 메모리(sbuf[6])가 바로 버퍼라는 용어로 사용됩니다.
즉, 포인터 변수는 버퍼와 같이 사용됩니다.
3-1) 변수와 포인터 예제 프로그램
▶ vi pointer.c
#include <stdio.h>
int main() {
int nval = 10;
int *nptr;
// 단일 변수에 대한 포인터
printf("대입전 메모리주소:[%p][%p]\n", &nval, nptr);
nptr = &nval;
printf("대입후 메모리주소:[%p][%p]\n", &nval, nptr);
printf("값: nval=[%d] nptr=[%d]\n", nval, *nptr);
return 0;
}
▶ 컴파일/실행
~/c-lecture (master ✘)✭ ᐅ gcc -o pointer pointer.c
~/c-lecture (master ✘)✭ ᐅ
~/c-lecture (master ✘)✭ ᐅ ./pointer
대입전 메모리주소:[0x7ffeb6cc6b3c][0x7ffeb6cc6c40]
대입후 메모리주소:[0x7ffeb6cc6b3c][0x7ffeb6cc6b3c]
값: nval=[10] nptr=[10]
~/c-lecture (master ✘)✭ ᐅ
▶ 분석
- 배열이 아닌 변수가 선언될때 크기 만큼 메모리가 할당되는데 이 메모리를 참조할때는
변수앞에 & 를 붙입니다. 변수앞에 &를 붙이면 이 의미는 변수의 메모리 주소라는 의미입니다.
c언어의 문법입니다. 변수앞에 &를 붙이면 메모리주소다 라고 외워주세요!! - 포인터는 주소값을 갖는 변수라고 말씀드렸는데요. 이렇게 변수의 주소를 포인터에 할당할 수 있습니다.
nptr = &nval; --> nval 변수의 주소를 포인터 nptr에 대입 - 포인터는 주소값을 갖는 변수지요. 그럼 그 주소에 들어있는 값을 참조할때는 포인터 변수명 앞에
* 를 붙입니다.
nval 의 값은 10입니다. *nptr의 값도 10이 됩니다.
&nval의 주소는 nptr과 같습니다.
변수 | 주소(어드레스) | 값 |
nval | &nval | 10 |
*nptr | nptr | *nptr |
- 예제 실행에서 nptr = &nval; 문 전 printf문입니다.
printf()에서 %p 서식은 주소를 출력하는 서식입니다. 포인터 공부 하실때 사용하시면 유용합니다.
대입전 메모리주소:[0x7ffeb6cc6b3c][0x7ffeb6cc6c40]
2개의 주소가 다르다는걸 아실수 있습니다. nptr값은 선언되면서 무작위의 값이 할당됩니다.(가비지)
nptr = &nval; 할당후 출력되는걸 보시면
대입후 메모리주소:[0x7ffeb6cc6b3c][0x7ffeb6cc6b3c]
같아진걸 보실수 있습니다. - 값을 출력하는 printf문을 보시면
printf("값: nval=[%d] nptr=[%d]\n", nval, *nptr);
nval은 변수 자체이지만 포인터 변수 nptr의 값을 출력할때는 *nptr로 사용됩니다.
3-2) char 배열과 포인터 예제 프로그램
▶ vi pointer2.c
#include <stdio.h>
int main() {
char sbuf[5] = {'h', 'e', 'l', 'l', 'o'};
char *sptr;
int i;
// 배열 변수에 대한 포인터
printf("대입전 메모리주소:[%p][%p]\n", sbuf, sptr);
sptr = sbuf;
printf("대입후 메모리주소:[%p][%p]\n", sbuf, sptr);
// 포인터를 사용해서 sbuf값을 출력
for (i = 0; i < 5; i++) {
printf("sbuf[%d]:주소-[%p][%p] 값-[%c][%c]\n", i, &sbuf[i], sptr+i, sbuf[i], *(sptr+i));
}
return 0;
}
▶ 컴파일/실행
~/c-lecture (master ✘)✭ ᐅ gcc -o pointer2 pointer2.c
~/c-lecture (master ✘)✭ ᐅ ./pointer2
대입전 메모리주소:[0x7ffda177f183][0x562caed4d080]
대입후 메모리주소:[0x7ffda177f183][0x7ffda177f183]
sbuf[0]:주소-[0x7ffda177f183][0x7ffda177f183] 값-[h][h]
sbuf[1]:주소-[0x7ffda177f184][0x7ffda177f184] 값-[e][e]
sbuf[2]:주소-[0x7ffda177f185][0x7ffda177f185] 값-[l][l]
sbuf[3]:주소-[0x7ffda177f186][0x7ffda177f186] 값-[l][l]
sbuf[4]:주소-[0x7ffda177f187][0x7ffda177f187] 값-[o][o]
~/c-lecture (master ✘)✭ ᐅ
▶ 분석
- char sbuf[5]; 배열로 선언하면 5바이트 크기의 메모리가 할당됩니다.
일반 변수에서 할당된 메모리를 참조할때는 & 를 붙여서 참조를 했는데
배열에서는 배열 이름 자체가 메모리의 주소가 됩니다. 이부분도 외워주세요!
char sbuf[5]에 할당된 메모리 주소의 시작은 sbuf입니다.
그런데 배열에서 3번째 주소를 알고 싶은 경우는 일반 변수처럼 & 를 붙여줍니다.
sbuf[2] 의 주소는 &sbuf[2] 입니다. - sptr = sbuf; 포인터 변수 대입전에는 2개의 주소가 서로 다릅니다.
여기서 배열에서는 변수명이 메모리 주소가 되어서 sbuf 를 그대로 포인터 변수에 대입합니다.
sbuf는 배열의 시작 주소라 말씀을 드렸는데요. 그래서 대입문은
sptr = &sbuf[0]; 으로도 가능합니다. 즉, sbuf = &sbuf[0] 입니다. - 포인트 변수 대입전
- 포인트 변수 대입
- printf("sbuf[%d]:주소-[%p][%p] 값-[%c][%c]\n", i, &sbuf[i], sptr+i, sbuf[i], *(sptr+i)); 출력문에서
배열 각각의 주소를 출력합니다. &sbuf[i] 로 출력합니다. 또한 포인터 변수로도 출력하는데
그 문법은 sptr+i로 하고 있습니다. 즉, &sbuf[i] == sptr + i 와 같습니다.
값을 출력할때 배열은 sbuf[i] 으로 배열의 값을 출력하고, 포인터로 값을 출력할때는
*(sptr+i) 로 출력합니다. sptr+i 가 각 배열의 주소를 뜻하고 포인터 값에 접근할 경우는 * 를 붙인다고 말씀을 드렸지요. 그래서 *(sptr+i) 주소앞에 * 를 붙인겁니다. 연산자 우선순위가 * 가 + 보다 앞서서 ()로 감싸줍니다. - 주소 출력 부분에서 눈여겨 보실게 있는데요.
sbuf[0]:주소-[0x7ffda177f183]
sbuf[1]:주소-[0x7ffda177f184]
sbuf[2]:주소-[0x7ffda177f185]
sbuf[3]:주소-[0x7ffda177f186]
sbuf[4]:주소-[0x7ffda177f187]
주소를 보시면 +1씩 증가한것을 보실수 있습니다. 이것은 char 타입이 1바이트라서 배열의 다음 주소가 1씩 증가합니다. 이렇게 메모리 주소를 다루는 변수가 포인터입니다.
3-3) int 배열과 포인터 예제 프로그램
▶ vi pointer3.c
#include <stdio.h>
int main() {
int nbuf[5] = {1, 2, 3, 4, 5};
int *nptr;
int i;
// 배열 변수에 대한 포인터
printf("대입전 메모리주소:[%p][%p]\n", nbuf, nptr);
nptr = nbuf;
printf("대입후 메모리주소:[%p][%p]\n", nbuf, nptr);
// 포인터를 사용해서 sbuf값을 출력
for (i = 0; i < 5; i++) {
printf("nbuf[%d]:주소-[%p][%p] 값-[%d][%d]\n", i, &nbuf[i], nptr+i, nbuf[i], *(nptr+i));
}
return 0;
}
▶ 컴파일/실행
~/c-lecture (master ✘)✭ ᐅ gcc -o pointer3 pointer3.c
~/c-lecture (master ✘)✭ ᐅ ./pointer3
대입전 메모리주소:[0x7fffeafb5cb0][0x55e4fac89280]
대입후 메모리주소:[0x7fffeafb5cb0][0x7fffeafb5cb0]
nbuf[0]:주소-[0x7fffeafb5cb0][0x7fffeafb5cb0] 값-[1][1]
nbuf[1]:주소-[0x7fffeafb5cb4][0x7fffeafb5cb4] 값-[2][2]
nbuf[2]:주소-[0x7fffeafb5cb8][0x7fffeafb5cb8] 값-[3][3]
nbuf[3]:주소-[0x7fffeafb5cbc][0x7fffeafb5cbc] 값-[4][4]
nbuf[4]:주소-[0x7fffeafb5cc0][0x7fffeafb5cc0] 값-[5][5]
~/c-lecture (master ✘)✭ ᐅ
▶ 분석
- char 배열을 int 배열로 바꿘본 예제입니다.
실행한 주소를 보시면 char 는 주소가 1씩 증가를 했는데 int 배열은 4씩 증가한 걸 보실수 있습니다.
int 타입의 크기가 4바이트입니다. 이렇게 타입에 따라서 메모리가 할당된 모습을 확인하실 수 있습니다.
printf("nbuf[%d]:주소-[%p][%p] 값-[%d][%d]\n", i, &nbuf[i], nptr+i, nbuf[i], *(nptr+i));
이문장을
printf("nbuf[%d]:주소-[%p][%p] 값-[%d][%d]\n", i, &nbuf[i], nptr, nbuf[i], *nptr);
nptr++;
이렇게 변경 가능합니다.
nptr주소로 *nptr은 주소에 대한 값으로 사용합니다.
nptr++; ++연산자로 포인터를 다음 데이타로 이동시킵니다.
nptr = &nbuf[0]; -> 1번째 배열 주소
nptr++; --> 2번째 배열 주소
nptr++; --> 3번째 배열 주소
...
포인터의 ++, -- 연산자는 struct 문법에서 다시 자세히 다루겠습니다.
'리눅스 C-언어 초급과정' 카테고리의 다른 글
14. 함수 파라메타 유형 (0) | 2022.11.17 |
---|---|
14. 함수 (0) | 2022.11.16 |
12. 문자열(string) (1) | 2022.11.16 |
11. 다차원 배열 (0) | 2022.11.16 |
10. 배열 (0) | 2022.11.16 |
- Total
- Today
- Yesterday
- Member
- 리눅스
- memset
- memcpy
- C언어
- 배열
- Call-By-Reference
- Clang
- sharetravelplan
- strcpy
- 재고
- 문자열
- 소켓
- 전처리기
- struct
- 포인터
- String
- #define
- Pointer
- GCC
- 파라메타
- While
- #ifdef
- array
- Linux
- #include
- Call-by-value
- IPC
- 의유
- c프로그램
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |