Develop
2003.04.23 10:56
[c] 포인터와 함수포인터에 대해..
조회 수 8195 댓글 0
포인터 종류
1. 객체 포인터
예)
int *ip;
-> ip는 int 타입의 객체를 가리키는 포인터
char *cp;
-> cp는 char 타입의 객체를 가리키는 포인터
2. 함수 포인터
예)
int (*fp)();
-> fp는 int를 리턴하는 함수를 가리키는 포인터
관련 연산자
& : 주소 연산자, 변수의 포인터(주소) 값을 만든다.
* : 간접 연산자. 포인터(주소)가 가리키는 곳의 값
다음 프로그램을 살펴보고 결과를 예측하라.
pointerop.c
1 #include <stdio.h>
2
3 main() {
4 int i, j, *ip;
5
6 ip = &i;
7 i = 22;
8 j = *ip;
9 *ip = 17;
10
11 printf("i = %dn", i);
12 printf("j = %dn", j);
13 printf("*ip = %dn", *ip);
14 }
% a.out
i = ?
j = ?
*ip = ?
함수 호출에서 포인터 넘기기(call-by-value)
passing_pointer.c
1 #include <stdio.h>
2
3 void h(int *p) {
4 printf("In h() : &p = %p t p = %p t *p = %dn", &p, p, *p);
5 }
6
7 main() {
8 int a = 10;
9
10 printf("In main : &a = %p t a = %d n", &a, a);
11 h(&a);
12 }
% a.out
In main : &a = effff9f8 a = 10
In h() : &p = effff9dc p = effff9f8 *p = 10
제네릭 포인터
모든 타입에 적용될 수 있는 포인터를 제네릭 포인터라고 한다.
ISO에서는 void * 를 제네릭 포인터로 지정하고 있다.
예)
void * gp;
int * ip;
char * cp;
gp = ip;
ip = gp;
ip = (int *) cp;
genswap.c
1 #include <stdio.h>
2 #include <malloc.h>
3 #include <sys/mem.h>
4
5 void swap(void *a, void *b, int n) {
6 void *t = malloc(n);
7
8 memcpy(t, a, n);
9 memcpy(a, b, n);
10 memcpy(b, t, n);
11 free(t);
12 }
13
14 void main(void) {
15 char c1='A', c2='B';
16 int i1=100, i2=200;
17 float f1=3.14, f2=33.33;
18
19 printf("nBefore : %c %c",c1,c2);
20 swap(&c1, &c2, sizeof(c1));
21 printf("tAfter : %c %c n",c1,c2);
22
23 printf("nBefore : %d %d", i1, i2);
24 swap(&i1, &i2, sizeof(int));
25 printf("tAfter : %d %dn",i1,i2);
26
27 printf("nBefore : %f %f ",f1,f2);
28 swap(&f1, &f2, sizeof(float));
29 printf("tAfter : %f %fn",f1,f2);
30 }
% a.out
Before : A B After : B A
Before : 100 200 After : 200 100
Before : 3.140000 33.330002 After : 33.330002 3.140000
널(Null) 포인터
C 언어에서는 특별한 포인터인 널 포인터를 지원한다.
널 포인터는 0, 0L, (void *)0 등으로 표현될 수 있다.
NULL 매크로는 3가지 널 포인터 중에서 한가지 형태를 갖을 수 있게 되어 있다.
예)
다음 문장
if(ip)
i = *ip;
는 아래 문장과 동일하다.
if(ip != NULL)
i = *ip;
포인터와 배열
배열과 포인터는 동일하지는 않지만 대부분의 경우에 동일하게 사용된다.
특히 식(expression)에서는 배열과 포인터는 서로 교환되어 사용될 수 있다.
예)
int a[10];
int *pa = &a[0]; /* int *pa = a; 와 동일 */
a[5]는 *(a + 5)와 동일하다.
sizeof(a) = ????
pnarray.c
1 #include <stdio.h>
2
3 main() {
4 int a[10] = { 3, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
5 int *pa = a;
6
7 printf("a[5] = %dn", a[5]);
8 printf("*(a+5) = %dn", *(a+5));
9 printf("*(pa+5) = %dn", *(pa+5));
10 printf("pa[5] = %dn", pa[5]);
11 printf("n*a+5 = %dn", *a+5);
12 printf("nsizeof(a) = %dn", sizeof(a));
13 }
% a.out
a[5] = 6
*(a+5) = 6
*(pa+5) = 6
pa[5] = 6
*a+5 = 8
sizeof(a) = 40
예)
int t[2][3];
t[1][2]은 *(*(t+1)+2)와 동일하다.
예)
int squash[23][12];
or
int * squash[23];
or
int ** squash;
or
int (* squash)[12]
*px++, (*px)++, *++px, ++*px
1.*px++ 는 *(px++) 와 동일하다. 결과적으로는 *px의 값을구하기는 하지만, 나중에 px를 1 만큼 증가시킨다.
2.(*px)++ 는 먼저 *px 값을 구한 후 *px 자체를 1 만큼 증가시킨다.
3.*++px 는 *(++px) 와 동일하다. 즉 먼저 px 를 1 만큼 증가시킨 후 *px 값을 구한다.
4.++*px 는 ++(*px) 와 동일하다. 즉 *px 의 값 자체를 1 만큼 증가시킨다.
포인터의 포인터
Pointer to pointer 는 그 대상 자체가 포인터인 포인터 변수이다.
포인터 변수는 어떤 변수의 번지를 저장하는 변수이다. 그러므로, Pointer to pointer 는
포인터의 번지를 기억한다
함수 포인터
1 #include <stdio.h>
2
3 void say(char * msg) {
4 printf("%sn", msg);
5 }
6
7 void exe(void (*fun)(char *), char* msg) {
8 fun(msg);
9 }
10
11 main() {
12 void (*hello)(char *);
13
14 hello = say;
15 hello("Hello World");
16 exe(hello, "HI~~");
17 }
% a.out
Hello World
HI~~
-
[c] 컴파일러 선행처리기 따라하기..
-
[c] 구조체/파일 입출력 프로그램
-
[c++] 더블 링크리스트(linked list) 학습용 초간단 단어장
-
[c] OpenGL 직사각형(2D) 크기 확대/축소
-
[jsp] 정적/동적(차트생성) 이미지 전달
-
[c] 프로세스간의 통신(파이프)
-
[c] 구조체의 설명과 예제..
-
[c] 포인터와 함수포인터에 대해..
-
[c] 스토리지 클래스(변수)
-
[c] 시간 관련 함수 설명과 예제..
-
[c] 문자열 처리 관련 함수들 설명
-
[linux] 프로세스 관련 시스템콜