[ C 언어 스터디 ]
자료출처 : 핵심 길잡이 C 프로그래밍 언어
도서출판 : 성안당
10. 포인터 ( Pointers )
★ 포인터의 개념 ★
포인터 ( pointer )는 데이터가 기억되어 있는 기억 장소의 주소( address )를 기호 형태
로 나타낸 것을 의미한다. 그러므로 기억된 데이터의 값을 참조하기 위해서는 변수를
사용하여 직접 참조할 수도 있고 포인터를 통하여 간접 찹조할 수도 있다.
포인터는 C 언어의 가장 대표적인 특징 중의 하나로 컴퓨터의 메모리를 간결하고
효율성 있게 제어하는 기능을 지니고 있다. 다음과 같은 경우에 주로 포인터를 사용
한다,
① 함수로부터 2개 이상의 값을 되돌려 줄 때
② 주소에 의한 호출 ( call by reference ) 방식의 경우
③ 한 함수에서 다른 함수로 편리하게 배열이나 문자열을 전달하고자 할 때
④ 링크드 리스트 ( linked list )나 이진 트리 ( binary tree )또는 하나의 데이터 구조
( data structure )가 다른 데이터 구조를 참조할 때 등과 같이 복잡한 데이터 구
조를 만들 때
주소 연산자 &는 변수의 주소를 나타낼 때 사용한다. 단순 변수, 배열 요소, 포인터
변수, 구조체 요소 앞에 붙어서 그들이 기억된 기억 장소의 위치, 즉 주소를 나타낸다.
예를 들어, num이 변수명이라면 &num는 변수 num의 주소를 의미한다.
다음 프로그램의 실행 결과를 나타내시오
▶ 프로그램
# include < stdio.h >
void main ( void )
{
int x ;
x=100 ;
printf ( " x = %d \n &x = %u \n " , x , &x ) ;
}
▶ 실행 결과
x = 100
&x = 50120
|
단, 변수 x의 주소는 시스템에 따라 달라질 수 있다.
이때 주소는 16진형( %x )이나 unsigned형( %u )으로 출력하면 된다. 간접 연산자 ( * )
는 포인터 변수 앞에 붙어서 그 포인터 변수가 가리키는 주소에 기억되어 있는 내용을
나타낸다. 예를 들면, 변수 num에 대하여
num == * ( &num ) ;
이 가능하다. 이것은 변수 num의 주소에 기억되어 있는 값을 의미한다.
★ 포인터 변수의 선언 ★
포인터 변수는 주소를 기억하는 변수이며 일반 선언 형식은 다음과 같다.
포인터 변수명은 일반 변수명을 정하는 규칙이 동일하게 적용된다. 그리고, 포인터
변수에는 반드시 데이터형을 지정하여야 한다. 왜냐하면, 포인터 변수가 가리키는 주소
에 어떤 형태의 데이터가 기억되어 있는지 프로그램이 알아야 하기 때문이다.
즉, 데이터는 그 형에 따라 길이가 달라지기 때문에 포인터가 가리키는 주소에서부
터 몇 바이트 ( byte )까지가 원하는 데이터 값인지를 알고 있어야 한다.
메모리 주소 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
|
Byte |
Byte |
Byte |
Byte |
Byte |
Byte |
Byte |
Byte |
기억된 값 |
'A' |
'212' |
'O.25 x 10ⁿ' |
|
|
100
ptr1 |
101
ptr2 |
103
ptr3 |
|
다음 프로그램의 실행 결과를 나타내시오
▶ 프로그램
# include < stdio.h >
void main ( void )
{
int *a ;
float *b ;
char *c ;
printf ( " 포인터의 변수 a의 크기 = %d Byte \n " , sizeof ( a ) ) ;
printf ( " 포인터의 변수 a의 크기 = %d Byte \n " , sizeof ( b ) ) ;
printf ( " 포인터의 변수 a의 크기 = %d Byte \n " , sizeof ( c ) ) ;
}
▶ 실행 결과
포인터 변수 a의 크기 = 4 Byte
포인터 변수 b의 크기 = 4 Byte
포인터 변수 c의 크기 = 4 Byte
|
위 예제에서와 같이 포인터 변수의 크기는 선언된 데이터형에 관계 없이 주소를
기억하는 데 필요한 크기로 int형과 같은 크기 ( 4 Byte )임을 알 수 있다. 여기서 크기는
시스템에 따라 달라질 수 있다.
포인터 변수에 주소값이 지정되면, 예를 들어,
int c , *ptr ;
ptr = &c ;
을 수행하면 다음과 같은 관계가 성립된다.
*ptr == c == *( &c )
&c == &( *ptr ) == ptr
다음 프로그램의 실행 결과를 나타내시오
▶ 프로그램
# include < stdio.h >
void main ( void )
{
int x=100 , *ptr ;
ptr = &x ;
printf ( " x = %d \n *ptr = %d \n " , x , *ptr ) ;
}
▶ 실행 결과
x = 100
*ptr = 100
|
다음 포로그램의 실행 결과를 나타내시오
▶ 프로그램
# include < stdio.h >
void main ( void )
{
int a[ ] = { 10 , 20 , 30 , 40 , 50 } ;
int i , *ptr ;
ptr = &a[ 0 ] ;
for ( i=0 ; i<5 ; i++ )
printf ( " a[ %d ]=%d
a[ %d ]의 주소 => %x \n " , i , *( ptr + i ) , i , &a[ i ] ) ;
printf ( " &ptr = %x \n " , &ptr ) ;
printf ( " ptr = %x \n " , ptr ) ;
}
▶ 실행 결과
a[ 0 ] = 10 |
a [ 0 ]의 주소 =>194 |
a[ 1 ] = 20 |
a [ 1 ]의 주소 =>196 |
a[ 2 ] = 30 |
a [ 2 ]의 주소 =>198 |
a[ 3 ] = 40 |
a [ 3 ]의 주소 =>19a |
a[ 4 ] = 50 |
a [ 4 ]의 주소 =>19b |
&ptr = ffda |
|
ptr = 194 |
|
|
위 예제의 실행 결과에서 각 배열 요소의 주소는 컴퓨터 시스템에 따라 다르게 나
타날 수 있다.
★ 배열과 포인터 ★
포인터와 배열은 밀접한 관계가 있다. 배열이 기억 장소에 기억될 때 배열의 요소들은
연속된 기억 장소에 기억된다. 그리고 배열명은 배열의 시작 주소를 가리키는 포인터 상수
이다. 그러므로 배열명을 기준 주소 ( base address )로 정하고, 배열의 각 요소가 몇 번째
요소인가를 나타내는 숫자를 더하여 줌으로써 배열의 요소를 포인터로 나타낼 수 있다.
< 1차원 배열과 포인터 >
다음과 같이 5개의 배열 요소로 구성된 1차원 배열이 있다고 하자 즉,
int a[ ] = { 10 , 20 , 30 , 40 , 50 } ;
int *ptr ;
ptr = a ;
a[ 0 ] |
a[ 1 ] |
a[ 2 ] |
a[ 3 ] |
a[ 4 ] |
배열 요소 |
10 |
20 |
30 |
40 |
50 |
배열 요소의 값 |
ptr |
ptr + 1 |
ptr + 2 |
ptr + 3 |
ptr + 4 |
|
와 같이 선언되었을 때 ,
*ptr == a[ 0 ] == *a == 10
*( ptr + 1 ) == a[ 1 ] == *( a+1 ) == 20
*( ptr + 2 ) == a[ 2 ] == *( a+2 ) == 30
*( ptr + 3 ) == a[ 3 ] == *( a+3 ) == 40
*( ptr + 4 ) == a[ 4 ] == *( a+4 ) == 50
이 성립한다.
다음 프로그램의 실행 결과를 나타내시오
▶ 프로그램
# include < stdio.h >
void main ( void )
{
int i , a[ ] = { 10 , 15 , 20 , 25 , 30 , 35 } ;
int *ptr ;
ptr = a ;
for ( i=0 ; i<6 ; i++ )
printf ( " a[ %d ] = %d \n " , i , *( ptr + i ) )
;
}
▶ 실행 결과
a[ 0 ] = 10 |
a[ 1 ] = 15 |
a[ 2 ] = 20 |
a[ 3 ] = 25 |
a[ 4 ] = 30 |
a[ 3 ] = 35 |
|
배열의 크기는 데이터형에 따라 달라질 수 있으나 , 그것이 몇 번째 요소인가는 데이
터형에 관계없이 일정하다. 예를 들어 다음과 같이 배열이 선언되어 있을 때 ,
char ch[ 3 ] = { 'A' , 'B' , 'C' } ;
int num[ 3 ] = { 10 , 20 , 30 } ;
float data[ 3 ] = { 0.5 , 1.2 , 0.75 } ;
각 배열의 요소는 배열명과 , 그 배열에서 몇 번째 요소인지를 나타내는 수를 더하여
표현할 수 있다. 즉 ch , ch+1 , ch+2 , num , num+1 , num+2 , data , data+1 , data+2
와 같이 나타낼 수 있다. 이들의 기억 형태는 다음과 같다.
배열 요소 |
ch[ 0 ] |
ch[ 0 ] |
ch[ 0 ] |
|
문자형 배열의 경우 포인터가 1씩 증가할 때마다 메모리가 1바이트씩 증가된다. 배
열 ch가 char형으로 선언되어 있기 때문에 각 배열 요소간의 간격이 1 바이트이다.
메모리 주소 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
|
Byte |
Byte |
Byte |
Byte |
Byte |
Byte |
|
배열 요소 |
num[ 0 ] |
num[ 1 ] |
num[ 2 ] |
|
정수형 배열의 경우에는 포인터가 1씩 증가할 때마다 메모리는 2바이트씩 증가된다.
배열 num이 int형으로 선언되어 있기 때문에 각 배열 요소간의 간격이 2바이트이다.
메모리 주소 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
|
Byte |
Byte |
Byte |
Byte |
Byte |
Byte |
Byte |
Byte |
Byte |
Byte |
Byte |
Byte |
배열 요소 |
data[ 0 ] |
data[ 1 ] |
data[ 2 ] |
실수형 배열의 경우에는 포인터가 1씩 증가할 때마다 메모리는 4바이트씩 증가된다.
배열 data가 float형으로 선언되어 있기 때문에 각 배열 요소간의 간격이 4바이트이다.
위의 그림에서 3개의 배열은 다음과 같은 관계가 성립된다.
ch == &ch[ 0 ] , |
*ch == ch[ 0 ] = 'A' |
ch+1 == &ch[ 1 ] , |
*( ch+1 ) == ch[ 1 ] = 'B' |
ch+2 == &ch[ 2 ] , |
*( ch+2 ) == ch[ 2 ] = 'C' |
|
num == &num[ 0 ] , |
*num == num[ 0 ] == 10 |
num+1 == &num[ 1 ] , |
*( num+1 ) == num[ 1 ] == 20 |
num+2 == &num[ 2 ] , |
*( num+2 ) == num[ 2 ] == 30 |
|
data == &data[ 0 ] , |
*data == data[ 0 ] == 0.5 |
data+1 == &data[ 1 ] , |
*( data+1 ) == data[ 1 ] == 1.2 |
data+2 == &data[ 2 ] , |
*( data+2 ) == data[ 2 ] == 0.75 |
여기서 *( num+1 )은 배열 num의 2번째 요소값 20을 나타내지만 *num+1은 배열
num의 첫 번째 요소의 값에 1을 더한 21이 된다. 왜냐하면 간접 연산자 *가 산술 연산
자 +보다 우선 순위가 높기 때문이다. 포인터는 다음과 같은 연산이 가능하다.
① 포인터 변수에 정수를 대입할 수 없다. 0는 대입할 수 있다. 이것은 NULL
포인터를 의미한다.
int *ptr ;
ptr = 100 ; //에러 발생
② 포인터 변수를 증가 또는 감소시킬 수 있다.
ptr++ ;
--ptr ;
③ 포인터에 정수를 더하거나 뺄 수 있다.
num+2 == num[ 2 ]
num+i == num[ i ]
④ 포인터의 크기를 비교할 수 있다.
⑤ 포인터의 데이터형이 같을 경우 포인터와 포인터의 감산이 가능하다.
< 2차원 배열과 포인터 >
2차원 배열도 1차원 배열과 배열 요소들이 기억 장소에 연속적으로 기억
되므로 포인터를 사용하여 직접 참조할 수 있다. 2차원 배열은 1차원 배열이라
고도 할 수 있다. 예를 들어,
int a[ 2 ][ 3 ] = { { 10 , 20 , 30 } , { 40 , 50 , 60 } } ;
int *ptr ;
ptr= a[ 0 ] ;
에서 배열 a는 2개의 배열 요소 a[ 0 ] , a[ 1 ]로 이루어져 있다. 이때 배열명 a는 2차원
배열의 선두 주소를 나타내는 포인터 상수이며, a[ i ]는 제 i 행의 선두 주소를 나타내는
포인터 상수이다. 그리고 a[ i ][ j ]는 2차원 배열에서 i 행 j 열의 요소를 나타내는 변수이
다.
따라서 a[ 0 ]는 a[ 0 ][ 0 ], a[ 0 ][ 1 ] , a[ 0 ][ 2 ]로 이루어져 있고, a[ 1 ]은 a[ 1 ][ 0 ] ,
a[ 1 ][ 1 ] , a[ 1 ][ 2 ]로 이루어져 있다. 그리고 배열명 a는 배열 a의 첫 번째 배열 요소
a[ 0 ]을 가리키고 , 다시 a[ 0 ]는 a[ 0 ][ 0 ]를 가리키므로 배열명 a의 포인터의 포인터라
할 수 있다.
배열 a의 기억 형태는 다음과 같다.
배열요소 |
a[ 0 ][ 0 ] |
a[ 0 ][ 1 ] |
a[ 0 ][ 2 ] |
a[ 1 ][ 0 ] |
a[ 1 ][ 1 ] |
a[ 1 ][ 2 ] |
메모리주소 |
1000 |
1001 |
1002 |
1003 |
1004 |
1005 |
1006 |
1007 |
1008 |
1009 |
1010 |
1011 |
포인터 |
ptr |
ptr+1 |
ptr+2 |
ptr+3 |
ptr+4 |
ptr+5 |
ptr+6 |
|
a[ 0 ] |
a[ 0] +1 |
a[ 0 ]+2 |
a[ 0 ]+3 |
a[ 0 ]+4 |
a[ 0 ]+5 |
a[ 0 ]+6 |
그러므로, 다음과 같은 관계가 성립된다.
ptr == a[ 0 ] == &a[ 0 ][ 0 ] |
*ptr == a[ 0 ][ 0 ] = 10 |
ptr+1 == a[ 0 ]+1 == &a[ 0 ][ 1 ] |
*( ptr+1 ) == a[ 0 ][ 1 ] = 20 |
ptr+2 == a[ 0 ]+2 == &a[ 0 ][ 2 ] |
*( ptr+2 ) == a[ 0 ][ 2 ] = 30 |
ptr+3 == a[ 1 ] == &a[ 1 ][ 0 ] |
*( ptr+3 ) == a[ 1 ][ 0 ] = 40 |
ptr+4 == a[ 1 ]+1 == &a[ 1 ][ 1 ] |
*( ptr+4 ) == a[ 1 ][ 1 ] = 50 |
ptr+5 == a[ 1 ]+2 == &a[ 1 ][ 2 ] |
*( ptr+5 ) == a[ 1 ][ 2 ] = 60 |
ptr = a ; 는 ptr == a이지만 , ptr+1은 a+1과 같지 않고 ptr+1==a[ 0 ]+1고 같다.
ptr은 포인터이고 a는 포인터의 포인터이기 때문이다. 그렇지만 a[ 0 ]는 포인터이다.
다음 포로그램의 실행 결과를 나타내시오
▶ 프로그램
# include < stdio.h >
void main ( void )
{
int i , a[ 3 ][ 4 ]={ { 10 , 15 , 20 , 25 } , { 30 , 35 , 40 , 45 } , { 50 , 55 , 60 , 65 } } ;
int *ptr ;
ptr = a[ 0 ] ;
for ( i=0 ; i<12 ; i++ )
printf ( " %d " , *( ptr+i ) ) ;
}
▶ 실행 결과
10 15 20 25 30 35 40 45 50 55 60 65
|
< 포인터 배열 >
C 언어에서는 포인트형 변수의 배열도 사용할 수 있다. 포인터 배열은 여러 개의 문
자열 데이터를 취급할 때 흔히 사용된다. 포인터 배열은 포인터를 배열 요소로 하며,
사용 형식은 다음과 같다.
형 식 |
데이터형 *포인터배열명 [ 요소의 개수 ] ; |
다음 프로그램의 실행 결과를 나타내시오
▶ 프로그램
# include < stdio.h >
void main ( void )
{
int i , *ptr[ 3 ] ;
int a=10 , b=20 , c=30 ;
ptr[ 0 ] = &a ;
ptr[ 1 ] = &b ;
ptr[ 2 ] = &c ;
for ( i=0 ; i<3 ; i++ )
{
printf ( " ptr+%d = %u \t ", i , ptr+i ) ;
printf (
" *( ptr+%d ) = %u \t " , i , *( ptr+i ) ) ;
printf ( " **( ptr+%d ) = %u \n " , i , *ptr[ i ] ) ;
}
}
▶ 실행 결과
ptr+0 = 65478 |
* ( ptr+0 ) = 65486 |
**( ptr+0 ) = 10 |
ptr+1 = 65480 |
* ( ptr+1 ) = 65488 |
**( ptr+1 ) = 20 |
ptr+2 = 65482 |
* ( ptr+2 ) = 65490 |
**( ptr+2 ) = 30 |
|
이때 기억 장소의 주소는 시스템에 따라 다르게 나타난다.
★ 문자열과 포인터 ★
문자열을 1차원의 문자형 배열로 나타내면 문자열을 구성하고 있는 각각의 문자들은
배열 요소들로 취급된다. 그런데 문자열 자체를 배열 요소로 하는 문자열 배열을 이용
하면 더욱 편리하다. 왜냐하면 첨자를 이용하여 문자열에 엑세스할 수 있기 때문이다.
문자열은 포인터 상수이며 , 문자열 배열은 이들을 배열 요소로 하기 때문에 포인터
배열이라고 할 수 있다. 문자열 배열의 선언 형식은 다음과 같다.
형 식 |
char *문자열배열명 [ 요소의 개수 ] ; |
예를 들어 ,
char *name[ 3 ]={ " hong " , " kim " , " park " } ;
와 같이 선언되었을 때 , 포인터 배열 name은 3개의 요소로 이루어져 있으며 , 이들 요
소들은 문자열의 시작 주소들을 기억한다. 이것을 그림으로 나타내면 다음과 같다.
포인터 배열요소 |
name == name[ 0 ] |
name+1 == name[ 1 ] |
name+2 == name[ 2 ] |
*name |
'h' |
'o' |
'n' |
'g' |
'\0' |
*( name+1 ) |
'k' |
'i' |
'm' |
'\0' |
*( name+2 ) |
'p' |
'a' |
'r' |
'k' |
'\0' |
그러므로 다음과 같은 관계가 성립한다.
*name[ 0 ] |
== **name == 'h' |
|
== *( *name+1 ) == 'o' |
|
== *( *name+2 ) == 'n' |
|
== *( *name+3 ) == 'g' |
|
== *( *name+4 ) == '\0' |
*name[ 1 ] |
== **( name+1 ) == 'k' |
|
== *( * ( name+1 )+1 ) == ' i ' |
|
== *( * ( name+2 )+2 ) == 'm' |
|
== *( * ( name+3 )+3 ) == '\0' |
*name[ 2 ] |
== **( name+2 ) == 'p' |
|
== *( * ( name+2 ) +1 ) == 'a' |
|
== *( * ( name+2 ) +2 ) == 'r' |
|
== *( * ( name+2 ) +3 ) == 'k' |
|
== *( * ( name+2 ) +4 ) == '\0' |
다음 프로그램의 실행 결과를 나타내시오
▶ 프로그램
# include < stdio.h >
void main ( void )
{
char *name[ 3 ]={ " hong " , " kim " , " park " } ;
int i ;
for ( i=0 ; i<3 ; i++ )
printf ( " %s \n " , name[ i ] ) ;
}
▶ 실행 결과
hong
kim
park
|
★ 이중 포인터 변수 ★
이중 포인터 변수란 포인터 변수에 다시 포인터를 지정한 것을 의미하며 이것을 포
인터에 대한 포인터락 한다. 사용 형식은 다음과 같다.
예를 들어
int **ptr ;
라고 선언하면 , *ptr은 포인터 변수 ptr이 가리키고 있는 주소의 값 즉 *ptr이 가리키
고 있는 위치의 주소의 값을 나타낸다.
다음 프로그램의 실행 결과를 나타내시오
▶ 프로그램
# include < stdio.h >
void main ( void )
{
int i , *p , **ptr ;
i=100 ;
p=&i ;
ptr=&p ;
printf ( " i = %d \n *p=%d \n **ptr=%d \n " , i , *p , **ptr ) ;
}
▶ 실행 결과
i=100
*p=100
**ptr=100
|
이것을 그림으로 나타내면 다음과 같다.
2060 |
2022 |
1020 |
메모리 주소 |
2022 --------> |
1020 --------> |
100 |
기억된 값 |
변수 ptr |
변수 p |
변수 i |
|
여기서 이중 포인터 변수 ptr은 포인터 변수 p의 주소를 기억하고 있고, 포인터 변
수 p는 변수 i의 주소를 기억하고 있다. 그러므로 **ptr은 ptr이 가리키는 주소의 값
( *p )이 가리키는 주소의 값 , 즉 변수 i 의 값이 된다.
★ 포인터와 함수 ★
함수 포인터는 수치 해석 분야에서 자주 사용하는 개념이다. 함수 포인터는 함수값
을 나타내는 포인터이다. 일반적으로 함수명을 수식 내에서 사용하면 그 함수를 가리키
느 포인터로 자동 변환된다.
함수 포인터를 사용하기 위해서는 먼저 사용할 포인터를 선언해야 하는데 그 형식은
다음과 같다.
형 식 |
● 호출 프로그램 ( calling program )
데이터형 *함수명 ( ) ;
● 피호출 프로그램 ( called program )
데이터형 *함수명 ( 매개변수리스트 )
매개변수리스트의 선언 ;
{
}
|
먼저 함수 포인터를 선언하려면 다음과 같이 정의해 준다.
형 식 |
데이터형 ( *포인터함수명 ) ( [ 매개변수리스트 ] ) ; |
예를 들어,
int ( *func ) ( ) ;
라고 선언하면 , *func는 func가 가리키고 있는 주소의 값을 나타낸다. 이때 * func에
있는 괄호를 생략하면 int형에 대한 포인터를 반환하는 함수를 선언하는 것으로 인식한
다. 함수 포인터가 특정 함수를 가리키게 하기 위해서는 함수 포인터에 함수명을 대입
하여 초기화한다. 이때 주의해야 할 것은 함수명에 대한 함수 선언을 먼저 해 주어야만
함수명을 대입할 수 있다는 것이다. 즉 ,
int sub ( ) ;
int ( *func ) ( ) ;
func = sub ;
와 같이 선언하면 함수 포인터 변수 func는 함수 sub을 가리키는 포인터를 기억하게
된다. 또한 포인터 변수를 통하여 간접적으로 함수를 호출하려면 변수에 간접 연산자
를 사용하여 매개변수들과 함께 쓰면 된다. 그 형식은 다음과 같다.
형 식 |
( * 포인터함수명 ) ( [ 매개변수리스트 ] ) ; |
예를 들어
double ( *ptr ) ( ) ;
double sin ( ) ;
ptr=sin ;
와 같이 선언되어 있다면 ptr=sin은 함수 sin( )이 위치에 있는 코드 세그먼트 영역
의 선두 주소를 대입하라는 뜻이다. 이때 함수명 앞에 주소 연산자 " & "를 사용하지 않
는다. 만약 이때 주소 연산자를 사용하면 에러가 발생한다.
ptr
---------> 함수를 가리키는 포인터를 의미
*ptr
--------> 함수 자체를 의미
( *ptr ) ( x )
-----> 함수를 호출한다는 것을 의미
다음 프로그램의 실행 결과를 나타내시오
▶ 프로그램
# include < stdio.h >
int plus ( int x , int y )
{
return ( x + y ) ;
}
void main ( void )
{
int ( *func ) ( ) ; // 함수의 원형
int a=10 , b=20 , c ;
func = plus ;
// 함수 plus의 주소를 함수 포인터 변수 func에 대입
c=( *func ) ( a , b )
;
printf ( " %d + %d = %d = %d \n " , a , b , c ) ;
}
▶ 실행 결과
10 + 20 = 30
|
< 함수 배열 포인터 >
함수 배열을 가리키는 포인터의 선언 형식은 다음과 같다.
형 식 |
데이터형 ( *포인터함수명 [ 첨자 ] ) ( ) ; |
예를 들어,
int ( *func [ 5 ] ) ( ) ;
와 같이 선언하면, 함수 배열의 결과로 정수형의 함수 배열 요소 func [ 0 ] ( ) ,
func [ 1 ] ( ) , func [ 2 ] ( ) ,
func [ 3 ] ( ) , func [ 4 ] ( ) , 5개가 준비된다. 그리고 , 함수 배열 포
인터를 사용할 경우 ,
int ( *func ) ( ) ;
는 int형 func가 가리키는 함수를 의미하고 ,
int *func ( ) ;
는 int형 포인터를 되돌려 주는 함수를 의미한다.
그리고 ,
int ( *func[ ] ) ( ) ;
는 int형 함수 배열 포인터를 의미한다.
다음 프로그램은 함수 배열을 가리키는 포인터를 사용하여 두 수 a , b의 값을 키보
드에서 입력받아 산술 연산을 수행한 결과를 나타내는 것이다.
다음 프로그램의 실행 결과를 나타내시오
▶ 프로그램
# include < stdio.h >
void main ( void )
{
int a , b , p[ 5 ] , i ;
int plus( ) , minus( ) , multiply( ) , divide( ) , remainder( ) , ( *ptr[ 5 ] ) ( ) ;
ptr[ 0 ]=plus ;
ptr[ 1 ]=minus ;
ptr[ 2 ]=multiply ;
ptr[ 3 ]=divide ;
ptr[ 4 ]=remainder ;
printf ( " 두 수 a , b의 값을 입력 : " ) ;
scanf( " %d
%d " , &a , &b ) ;
for ( i=0 ; i<5 ; i++ )
{
p[ i ]=( *ptr[ i ] ) ( a , b )
printf ( " p[ %d ]=%d \n " , i ,p[ i ] ) ;
}
}
plus( int x , int y )
{ return ( x+y) ; }
minus( int x , int y )
{ return ( x-y) ; }
multiply( int x , int y )
{ return ( x*y) ; }
divied( int x , int y )
{ return ( x/y) ; }
remainder( int x , int y )
{ return ( x%y) ; }
▶ 실행 결과
두 수 a , b의 값을 입력 : 30 6 Enter Button Push
p[ 0 ]=36
p[ 1 ]=24
p[ 2 ]=180
p[ 3 ]=5
p[ 4 ]=0
|