logo정처기 감자

Command Palette

Search for a command to run...

C언어 함수 포인터 (Function Pointer)

코딩C언어
C언어 함수 포인터 (Function Pointer)
읽는데 13분 소요
처음 쓰여진 날: 2026-04-19
마지막 수정일: 2026-04-24
조회수: —
선수학습(3개)
  • C언어 포인터의 기초
  • C언어 함수 프로토타입
  • C언어 구조체

요약

C언어 함수 포인터의 선언 문법과 호출 방법을 알아봅니다. int* (*fn)(int*) 같은 복잡한 선언 해석, 구조체 멤버로 함수 포인터 사용, 함수 포인터 배열(int (*fns[N])(int))까지 정보처리기사 실기 26년1회 기출 대비 핵심 개념을 정리합니다.

함수 포인터 핵심 정리

아래 표는 이 페이지에서 다룰 개념을 미리 정리한 것입니다. 지금 바로 이해가 안 돼도 괜찮습니다. 아래 본문에서 하나씩 풀어서 설명합니다.

개념설명예시
함수 포인터 선언함수의 주소를 저장하는 포인터int (*fp)(int);
함수 이름그 자체가 함수의 시작 주소fp = dummy; (&dummy와 같음)
함수 포인터 호출저장된 함수를 실행fp(3) 또는 (*fp)(3)
구조체 멤버 함수 포인터구조체 안에 함수 포인터를 멤버로 두기struct { int (*fn)(int); } s;
함수 포인터 배열여러 함수의 주소를 배열에 담아 인덱스로 호출int (*fns[3])(int); fns[0](x);

함수 포인터란? 기초

프로그램을 실행하면 함수 코드도 메모리 어딘가에 올라갑니다. 그 시작 위치에는 주소가 있고, C언어는 이 주소를 변수에 담을 수 있습니다. 이것이 함수 포인터(Function Pointer) 입니다.

포인터는 "주소를 저장하는 변수"입니다. 변수 포인터가 int 같은 값이 들어 있는 주소를 담듯, 함수 포인터는 함수 코드가 시작되는 주소를 담습니다.

처음 보면 int (*fp)(int) = add; 한 줄에 모르는 문법이 여러 개 겹쳐 있습니다. 아래에서 하나씩 분리해서 이해하고, 마지막에 합쳐서 읽겠습니다.

1단계: 함수 포인터 선언 — int (*fp)(int);

int를 받아 int를 돌려주는 함수의 주소를 담을 수 있는 포인터 fp를 선언합니다. 선언 문법의 세부 내용은 아래 섹션에서 자세히 다룹니다.

2단계: 함수 이름은 주소다 — add

add라는 함수 이름은 그 자체로 함수가 올라간 메모리 주소를 의미합니다. &add라고 써도 같은 주소이지만, 관습적으로 &를 생략합니다.

3단계: 포인터에 주소 저장 — fp = add;

변수 포인터에 변수 주소를 넣듯(int *p = &x;), 함수 포인터에 함수 주소를 넣습니다.

4단계: 저장된 주소로 호출 — fp(10)

fp에는 add의 주소가 들어 있습니다. fp(10)을 실행하면 C언어가 그 주소로 이동해 add(10)을 실행합니다. 결과는 add(10) → 10 + 1 → 11입니다.

c
코드 하이라이팅 중...
함수 포인터 fp의 기본 동작: add 함수가 코드 메모리 주소 0xA100에 위치하고 fp 변수에 그 주소를 저장하면 fp(10) 호출이 add(10)로 점프해 11을 반환하는 흐름
fp는 add 함수의 시작 주소를 담은 변수 — fp(10) 호출은 그 주소로 점프하여 add(10)을 실행
함수 포인터도 결국 '주소를 담는 변수'입니다
함수 포인터가 특별해 보이지만, 본질은 변수 포인터와 같습니다. 일반 포인터는 int·char 같은 값이 저장된 주소를 담고, 함수 포인터는 함수 코드가 저장된 주소를 담습니다. 주소만 있으면 그 주소의 함수를 실행할 수 있습니다.

함수 포인터에서 *는 두 가지 전혀 다른 역할로 등장합니다.

위치코드 예*의 역할
선언부int (*fp)(int);"fp는 포인터다"라는 표시 (타입 선언)
호출부(*fp)(10)fp가 가리키는 함수로 이동 (역참조1)

(*fp)(10) 호출 방식은 "포인터가 가리키는 함수를 역참조해서 호출"하는 원형 표기입니다. 현대 C언어는 fp(10) 축약 표기도 허용하므로 두 방식이 동일합니다.


함수 포인터 선언 문법 기초

함수 포인터 선언은 처음 볼 때 복잡해 보이지만, 세 부분으로 나눠서 읽으면 쉽습니다.

c
코드 하이라이팅 중...
위치의미
int (맨 앞)이 함수가 반환하는 자료형
(*fp)이름은 fp, 그 앞의 *는 "포인터"라는 표시
(int) (맨 뒤)이 함수가 받는 매개변수 자료형

즉 int (*fp)(int);는 "int 하나를 받아서 int를 돌려주는 함수의 주소를 저장하는 포인터 fp" 를 뜻합니다.

괄호가 꼭 필요한 이유

(*fp) 의 괄호를 빼고 int *fp(int); 이라고 쓰면 완전히 다른 의미가 됩니다.

선언해석
int (*fp)(int);int를 받아 int를 돌려주는 함수의 포인터
int *fp(int);int를 받아 int 포인터를 돌려주는 함수의 프로토타입

*를 먼저 fp에 묶어야 "fp는 포인터"가 되기 때문에 괄호 ( ) 가 필요합니다.

반환형이 포인터인 경우

반환형 자리에 int*처럼 포인터 타입을 쓸 수도 있습니다.

c
코드 하이라이팅 중...

이 선언은 "int*를 받아 int*를 돌려주는 함수의 포인터 fp"입니다. 26년1회 기출 문제의 int* (*fn)(int*) 가 바로 이 형태입니다.


함수 포인터에 함수 할당 기초

선언된 함수 포인터에 실제 함수를 연결하려면 함수 이름을 대입합니다.

c
코드 하이라이팅 중...

함수 이름은 변수와 달리 이름 자체가 주소입니다. 변수 포인터와 나란히 놓고 보면 차이가 명확합니다.

c
코드 하이라이팅 중...

fp = add; 는 "fp에 add 함수의 시작 주소를 저장"하는 것이므로, fp = &add; 와 같은 의미입니다.

대입 시 두 함수의 매개변수 개수·위치별 타입·반환 타입이 세 가지 모두 일치해야 합니다. 하나라도 다르면 컴파일 경고(GCC) 또는 오류(MSVC)가 납니다.


함수 포인터로 함수 호출 기초

함수 포인터에 함수를 연결한 뒤에는 일반 함수처럼 호출합니다.

c
코드 하이라이팅 중...

두 가지 호출 방식이 모두 허용됩니다.

표기해석
fp(10)"fp가 가리키는 함수에 10을 넘겨 호출" (권장)
(*fp)(10)"fp를 역참조한 함수에 10을 넘겨 호출" (원형)

C 언어는 두 표기를 똑같이 처리하므로, 시험에서는 어느 쪽이 나와도 같은 의미로 읽으면 됩니다.

시험 출제 경향: 정보처리기사 실기에서는 (*fp)(인자) 역참조 형태가 주로 출제됩니다. 두 방식이 동일하다는 것만 기억하면 어느 표기가 나와도 당황하지 않습니다.


구조체 멤버로 함수 포인터 두기 심화

이 패턴은 구조체와 함수 포인터를 먼저 이해한 뒤 보세요
구조체의 멤버 접근(.)과 함수 포인터 선언이 한 줄에 섞여 있으므로, 두 개념을 따로 익힌 뒤 합쳐서 읽어야 합니다. 26년1회 기출에서 출제된 패턴입니다.

구조체 안에도 함수 포인터를 멤버로 넣을 수 있습니다. 예를 들어 "학생 구조체에 점수를 계산하는 함수를 함께 담는다"처럼, 데이터(멤버 변수)와 행동(함수 포인터)을 하나의 구조체로 묶는 패턴입니다.

c
코드 하이라이팅 중...

코드 해석 순서

  1. struct fns { int* (*fn)(int*); } mine;
    • } 닫는 중괄호 바로 뒤에 변수명 mine을 붙이면 구조체 타입 정의와 변수 선언을 한 줄에 할 수 있습니다. struct fns mine;을 따로 쓰는 것과 결과가 같습니다. 이 문법은 구조체 페이지의 즉시 변수 선언 섹션에서 자세히 다룹니다.
    • mine.fn은 "int*를 받아 int*를 돌려주는 함수"의 주소를 담을 수 있습니다.
  2. mine.fn = dummy;
    • dummy는 int*를 받아 int*를 돌려주는 함수이므로 매개변수·반환 타입이 일치합니다.
    • 이제 mine.fn을 호출하면 dummy가 실행됩니다.
  3. *mine.fn(n)
    • 호출 표기를 분해하면 *( mine.fn(n) ) 입니다. 뒤에서 자세히 다룹니다.

*mine.fn(n) 의 연산자 우선순위

함수 호출 () 는 역참조 * 보다 우선순위가 높습니다. 따라서 *mine.fn(n)은 다음 순서로 해석됩니다.

단계수행 내용결과
1mine.fn — 구조체 멤버로 저장된 함수 포인터를 꺼냄dummy 함수의 주소
2mine.fn(n) — 꺼낸 함수에 n을 넘겨 호출 (= dummy(n))n + 1 (배열 두 번째 요소의 주소)
3*mine.fn(n) — 2단계의 반환값(주소)에 역참조n[1] = 32

2단계에서 n + 1이 두 번째 요소 주소인 이유: 배열 이름 n은 첫 번째 요소 n[0]의 주소입니다. int 포인터에 1을 더하면 다음 int 크기(4바이트)만큼 이동하므로 n + 1은 n[1]의 주소가 됩니다.

n[] = {16, 32} 이고 dummy(n) 이 n + 1을 돌려주므로, 역참조 결과는 두 번째 요소 32입니다.

printf("%x", 32) 는 32를 16진수로 출력합니다. 32를 16진수로 변환하면 32 ÷ 16 = 2 나머지 0이므로 20이 나옵니다. %x는 16진수를 소문자로 출력하는 서식 지정자입니다.

구조체 멤버 함수 포인터 *mine.fn(n) 실행 흐름: mine.fn으로 dummy 함수 주소를 꺼내고, dummy(n)을 호출해 n+1(주소 104)을 반환받은 뒤, 역참조하여 n[1]=32를 얻어 %x로 20을 출력하는 3단계
*mine.fn(n) 3단계 실행 흐름 — 멤버 접근 → 함수 호출 → 역참조

함수 포인터 배열 심화

여러 함수를 배열에 담아 인덱스로 골라 호출하는 패턴입니다. 예를 들어 "연산 번호(0=덧셈, 1=뺄셈, 2=곱셈)를 받아 해당 연산 함수를 호출"하는 식으로, 인덱스 하나만 바꿔 다른 함수를 즉시 선택할 수 있습니다.

선언 문법 분해

c
코드 하이라이팅 중...
위치의미
int (맨 앞)각 함수의 반환 타입
(*fns[3])크기 3의 배열 fns, 각 원소는 함수를 가리키는 포인터
(int) (맨 뒤)각 함수의 매개변수 타입

즉 int (*fns[3])(int);은 "int를 받아 int를 돌려주는 함수의 주소를 3개까지 담는 배열 fns" 를 뜻합니다.

함수 포인터 선언과 마찬가지로, 괄호 ( ) 가 없으면 의미가 완전히 달라집니다. *와 [3]을 괄호로 fns에 먼저 묶어야 "fns는 함수 포인터들의 배열"이 됩니다.

선언해석비고
int (*fns[3])(int);int를 받아 int를 돌려주는 함수 포인터 3개의 배열올바른 선언
int *fns[3](int);int*를 돌려주는 함수를 원소로 갖는 배열컴파일 에러 — C는 함수 배열을 허용하지 않음

초기화와 인덱스 호출

선언과 동시에 중괄호 { } 안에 함수 이름을 나열하면 각 원소에 함수 주소가 할당됩니다.

c
코드 하이라이팅 중...
함수 포인터 배열 fns[3]의 각 원소가 add, sub, mul 함수 주소를 담고 인덱스를 통해 해당 함수로 점프하는 메모리 구조
fns[0]=add, fns[1]=sub, fns[2]=mul — 배열 원소가 함수 주소를 담는 구조

초기화 시 { add, sub, mul } 순서대로 fns[0]=add, fns[1]=sub, fns[2]=mul이 저장됩니다. fns[0]은 배열의 첫 원소 — add 함수의 주소입니다. fns[0](10)은 "그 주소의 함수에 10을 넘겨 호출"이므로 add(10)과 동일합니다. 마찬가지로 fns[1](10)은 sub(10), fns[2](10)은 mul(10)을 실행합니다.

반복문으로 순회하며 호출

for 문으로 인덱스를 바꿔가며 같은 입력을 여러 함수에 적용할 수 있습니다. 이 패턴이 함수 포인터 배열의 전형적인 용도입니다.

c
코드 하이라이팅 중...
for 루프 i=0,1,2 반복별로 fns[i]가 add, sub, mul 함수로 바뀌며 각각 11, 9, 20을 출력해 최종 11 9 20을 만드는 루프 순회 흐름
for 루프 반복별 fns[i] 호출과 출력 누적

출력: 11 9 20

반복 변수 i가 0, 1, 2로 바뀌면서 매 반복마다 다른 함수(add, sub, mul)가 10을 인자로 호출됩니다.

구조체와 조합

구조체 멤버 함수 포인터와 합치면 여러 동작을 하나의 묶음으로 관리할 수 있습니다.

c
코드 하이라이팅 중...
struct Calc c 안의 ops[3] 배열이 add, sub, mul 함수 주소를 담고 c.ops[1](10)이 sub(10)=9로 연결되는 구조체-배열-함수 3층 구조
struct Calc → ops[3] 배열 → 함수 주소 3층 구조, c.ops[1](10) = sub(10)

{ { add, sub, mul } } 에서 바깥 { }는 구조체 초기화, 안쪽 { }는 배열 멤버 ops 초기화입니다.

c.ops[1](10)은 "구조체 c의 멤버 ops의 1번 원소(sub의 주소)에 10을 넘겨 호출"이므로 sub(10)과 같습니다.


정보처리기사 실기 대비 문제 기초


Footnotes

  1. 역참조: *를 사용해 포인터가 가리키는 주소로 이동해 그 내용에 접근하는 연산입니다. 변수 포인터에서는 *p로 값을 읽고, 함수 포인터에서는 (*fp)(인자)로 함수를 실행합니다. ↩


메가커피와 함께, 홈페이지 개선에 참여하세요! ☕
혹시 이용에 불편한 점이나 개선이 필요한 부분을 발견하셨나요? 댓글로 알려주시면 더 나은 감자가 될 수 있어요! 🥔 제보해주신 모든 분께 메가커피 기프티콘을 드립니다! (본인 이메일로 댓글 달아주셔야해요~)
후수학습(1개)
  • C언어 구조체 포인터

관련 글

(41개)
제목태그업데이트시험
C언어 형변환 (Casting)
C언어코딩C언어
2026-05-15-
C언어 연결 리스트 뒤집기 (Reverse Linked List)
C언어코딩C언어
2026-05-06-
C언어 사용자 정의 함수 기초
C언어코딩C언어
2026-05-06-
정처기 감자정처기 감자

정보처리기사 합격
도와줄라고 하는 감자

실기 이론

  • 이론 공부법
  • DB
  • 네트워크/OS
  • SW 설계
  • SW 개발
  • 보안/신기술

시험 응시

  • 시험장 찾기
  • 원서 접수
  • 응시자격 서류

요약 PDF

  • 26년 1회 이론 압축
  • 초압축 25년 3회
  • 압축 25년 3회

기출문제

  • 전체 기출문제
  • 25년 3회
  • 25년 2회
  • 문제 포럼

감자 이용권

  • 이용권 구매

실기 이론

  • 이론 공부법
  • DB
  • 네트워크/OS
  • SW 설계
  • SW 개발
  • 보안/신기술

시험 응시

  • 시험장 찾기
  • 원서 접수
  • 응시자격 서류

요약 PDF

  • 26년 1회 이론 압축
  • 초압축 25년 3회
  • 압축 25년 3회

기출문제

  • 전체 기출문제
  • 25년 3회
  • 25년 2회
  • 문제 포럼

감자 이용권

  • 이용권 구매
© 2025 재현기획개발. All rights reserved.
  • 정처기 감자의 시작
  • 업데이트 로그
  • 개인정보 처리방침
  • 이용약관
상호명 : 재현기획개발 / 주소: 서울특별시 영등포구 영등포로 150, 지하1층 108호 L145 가라지(당산동1가, 생각공장 당산) / 대표: 김재현 / 전화: 010-8158-7127 / 통신판매업신고: 제2025-서울영등포-1569호 / 이메일: contact@edugamja.com / 사업자등록번호: 573-51-00999