C/C++ 학습 · 11 min read · Oct 09, 2025

C/C++ 단계별 학습 - 페이지 6

06. 단계별 C/C++ — C 프로그래밍 - 함수

함수

I. 소개
II. 함수 정의
III. 함수의 종류
IV. 내장 함수

| | 1. 수치 함수

  1. 문자열 함수
  2. 문자 테스트 함수 | | | V. 사용자 정의 함수 | | | 1. 간단한 함수
  3. 인수가 있는 함수
  4. 반환값이 있는 함수
  5. 재귀 함수 | | | VI. 포인터와 함수 | | | 1. 참조에 의한 매개변수 전달
  6. 값에 의한 호출
  7. 참조에 의한 호출 | | | VII. 지역 변수와 전역 변수 | | | VIII. 저장 클래스 지정자 | | | 자동 저장 클래스
    레지스터 저장 클래스
    정적 저장 클래스
    외부 저장 클래스 |

I. 소개

여기 사람의 주소를 두 번 인쇄하는 프로그램이 있습니다. 이는 함수 사용과 함수 미사용 두 가지 방법으로 작성되었습니다. 이는 함수의 장점을 보여줄 것입니다.

| | #include
int main()
{
printf(“\n이름”);
printf(“\n거리, 아파트//집 번호”);
printf(“\n우편번호, 도시”);
printf(“\n국가“);

printf(“\n이름”);
printf(“\n거리, 아파트//집 번호”);
printf(“\n우편번호, 도시”);
printf(“\n국가“);

return 0;
} | #include
void address()
{
printf(“\n이름”);
printf(“\n거리, 아파트//집 번호”);
printf(“\n우편번호, 도시”);
printf(“\n국가“);
}

int main()
{
address();
address();

return 0;
} |

II. 함수 정의

값을 인수로 받아들이고 호출 프로그램에 결과를 반환할 수 있는 문장 블록입니다. 따라서 함수는 특정 작업을 수행하는 독립적인 문장 블록입니다.

III. 함수의 종류

| | - 내장 함수/ 라이브러리 함수/ 미리 정의된 함수

  • 사용자 정의 함수 |

IV. 라이브러리 함수

라이브러리 함수는 소프트웨어 제조업체에 의해 설계되며, 소프트웨어가 로드될 때마다 디스크에 로드됩니다.

다음 함수는 라이브러리 함수의 예입니다.

1. 수치 함수

함수구문예.결과
AbsAbs(n)abs(-35)35
ceilceil(n)ceil(45.232)46
floorfloor(n)floor(45.232)45
fmodfmod(n,m)fmod(5,2)1
coscos(n)cos(60)0.5
sinsin(n)sin(60)0.866
tantan(n)tan(60)1.732
sqrtsqrt(n)sqrt(25)5
powpow(n,m)pow(2,3)8

2. 문자열 함수

함수구문예.
strlenstrlen(str)strlen(“컴퓨터”)
strcpystrcpy(target,source)strcpy(res,”Pass”)
strcatstrcat(target,source)strcat(“mag”,”gic”)
strcmpstrcmp(str1,str2)strcmp(“abc”,”Abc”)
strrevstrrev(target,scr)fstrrev(res,”LIRIL”)

3. 문자 테스트 함수

함수설명
isalnum문자 또는 숫자 여부
isalpha문자 여부
isdigit숫자 여부
iscntrl일반 제어 문자 여부
isascii유효한 ASCII 문자 여부
islower소문자 여부
isupper대문자 여부
isspace공백 문자 여부
isxdigit16진수 문자 여부

사용 가능한 함수의 방대한 라이브러리가 있으며, 저는 그 중 일부만 제공했습니다. 더 많은 라이브러리 함수는 도움말 매뉴얼을 참조하십시오.

V. 사용자 정의 함수

이미 본 프로그램은 노동 분담을 수행합니다. gets, puts 또는 strcmp를 호출할 때 이러한 함수의 내부 작동 방식에 대해 걱정할 필요가 없습니다.

이러한 함수와 약 400개의 다른 함수는 Turbo C 라이브러리에 이미 정의되고 컴파일되어 있습니다. 이를 사용하려면 프로그램에 적절한 헤더 파일을 포함하기만 하면 됩니다. “런타임 라이브러리”에서 함수 호출 방법과 반환되는 값(있는 경우)을 이해해야 합니다.

하지만 자신의 함수를 작성해야 합니다. 그렇게 하려면 코드를 각 함수가 단일하고 이해할 수 있는 작업을 수행하는 개별 섹션(함수)으로 나누어야 하며, 이를 통해 프로그램 전반에 걸쳐 C 라이브러리 함수를 호출하는 것과 같은 방식으로 호출할 수 있습니다.

함수를 구현하는 단계

| | 1. 선언

  1. 함수 호출
  2. 정의 |

| | • 모든 함수는 프로그램의 시작 부분에 선언되어야 합니다.
• 함수 정의는 실행 작업의 실제 코드를 포함합니다.
• 함수가 프로그램의 시작 부분에 정의되어 있으면 함수 선언이 필요하지 않습니다. |

함수 구현을 보여주는 예제

| | / 32_egfun.c /
#include

void address(); / 선언 /

int main()
{
address(); / 함수 호출 /
address(); / 함수 호출 /

return 0;
}

void address() / 정의 /
{
printf(“\n이름”);
printf(“\n거리, 아파트//집 번호”);
printf(“\n우편번호, 도시”);
printf(“\n국가“);
} |

사용자 정의 함수는 호출 방식에 따라 4가지 유형으로 나눌 수 있습니다.

| | 1. 간단한 함수

  1. 인수가 있는 함수
  2. 반환값이 있는 함수
  3. 재귀 함수 |

1. 간단한 함수

특정 작업만 수행하며, 인수나 반환 값이 필요하지 않습니다.

간단한 함수의 예

| | / 33_line.c /
#include
void line(); / 선언 /
int main()
{
line(); / 함수 호출 /
return 0;
}
void line() / 정의 /
{
int i;
for(i =1;i<80; i++)
putch(‘*’);
} |

2. 인수가 있는 함수

인수를 받아들이는 함수는 인수가 있는 함수라고 합니다.

예:

| | / 34_argu.c /
void line(char ch, int n)
int main()
{
line(“-“, 50);
line(“*”, 8);
return 0;
}
void line(char ch, int n)
{
int i;
for( i = 1; i<=n; i++ )
putch(ch);
} |

3. 반환값이 있는 함수

호출 프로그램에 값을 반환할 수 있는 함수는 반환값이 있는 함수라고 합니다.

예:

| | / 35_retu.c /
int abs(int n);
int main()
{
int res;
printf(“%d”, abs(-35))

res = abs(-34); / 함수 호출/

printf(“%d”, res);
return 0;
}
void abs(int n)
{
if( n < 0 )
n = n * -1;
return n;
} |

4. 재귀 함수

함수 본문 내의 문장이 동일한 함수를 호출하는 것을 ‘재귀‘라고 합니다. 때때로 ‘순환 정의’라고도 하며, 재귀는 어떤 것을 스스로 정의하는 과정입니다.

재귀 함수의 예

| | / 다음 프로그램은 자기 호출 함수를 보여줍니다 /
int main( )
{
printf(“\n안녕하세요“);
main( ); / 자기 호출 함수 /
return 0;
} 실행하지 마십시오. 이 프로그램은 여전히 설명이므로 논리적으로 유효하지 않습니다.
다른 함수를 사용하여 동일한 출력을 얻을 수 있습니다: void disp( );

int main( )
{
disp( );
return 0;
}

void disp( )
{
printf(“\n안녕하세요“);
disp( );
} |

프로그램은 특정 시점에 종료되어야 하므로 재귀의 핵심은 조건문을 사용하여 정의할 수 있는 소프트 인터럽트에 있습니다. 다음 예제를 확인하십시오:

| | / 36_recursion.c /
int i = 1;      / 전역 변수 선언 /
void disp( );
int main( )
{
disp( );
return 0;
}

void disp( )
{
printf(“\n안녕하세요 %d “, i);
i ++;
if( i < 10 ) / i 값이 10보다 작으면 함수를 다시 호출 /
disp( );
} |

| | 주어진 숫자의 팩토리얼을 찾는 프로그램:
/ 37_fact.c /
int factorial(int x);
void main
{
int a, fact;
printf(“\n숫자를 입력하세요 “); scanf(“%d”, &a);
fact = factorial(a);
printf(“\n팩토리얼은 = %d”, fact);
}
int factorial(int x)
{
int f = 1, i;
for( i = x; i>=1; i–)
f = f i;
return f;
} | 재귀를 사용하여 주어진 숫자의 팩토리얼을 찾기
/
38_fact.c /
int rec_fact(int x);
int main( )
{
int a, fact;
printf(“\n숫자를 입력하세요 “); canf(“%d”, &a);
fact = rec_fact(a);
printf(“\n팩토리얼 값은 = %d”, fact);
return 0;
}
int f = 1;
int rec_fact(int x)
{
if( x > 1)
f = x
rec_fact(x-1);
return f;
} |

VI. 포인터와 함수

| | 참조에 의한 매개변수 전달
값에 의한 호출
참조에 의한 호출
|

1. 참조에 의한 매개변수 전달

포인터는 함수 선언에 사용할 수 있으며, 이를 통해 복잡한 함수를 쉽게 표현하고 접근할 수 있습니다. 함수 정의는 두 가지 방법으로 포인터를 사용합니다.

| | – 값에 의한 호출

  • 참조에 의한 호출 |

참조에 의한 호출 메커니즘은 값에 의한 호출 메커니즘보다 빠릅니다. 왜냐하면 참조에 의한 호출에서는 주소가 전달되며 주소와의 조작이 일반 변수보다 빠르기 때문입니다. 또한 실제 매개변수마다 하나의 메모리 위치만 생성됩니다.

프로그램의 일부인 실제 인수가 함수를 호출하고 함수 내에서 변경된 값은 호출 프로그램의 호출 부분에 변경된 형태로 반환됩니다. 이를 참조에 의한 호출 또는 주소에 의한 호출이라고 합니다. 이 메커니즘에서 함수 인수로 포인터를 사용하면 데이터 객체를 전역적으로 변경할 수 있습니다. 즉, 함수 내에서뿐만 아니라 호출 프로그램 내에서도 변경할 수 있습니다. 포인터가 함수에 전달되면 인수의 주소가 함수에 전달되고 이 주소의 내용은 전역적으로 접근됩니다. 형식 매개변수(함수에서 사용되는 매개변수)에 대한 변경 사항은 실제 매개변수(호출 프로그램에서 함수 호출에 사용되는 매개변수)의 원래 값에 영향을 미칩니다.

예:

| | / 39_func.c /

void func_c( int *x );

int main()
{
int i = 100;
int *a;
a = &i;
printf(“\n값은 %d”, i);
func_c(a);
printf(“\n값은 %d”, i);
return 0;
}

void func_c( int x )
{
(
x) ++;
printf(“\n함수 내의 값은 %d “, *x);
} |

위 프로그램에서는 총 세 개의 ‘printf’ 문이 있습니다. 두 개는 main() 함수에 있고 하나는 함수 서브프로그램에 있습니다. 첫 번째 printf 문으로 인해 i의 값이 100으로 출력됩니다. 이후 함수 호출이 이루어지고 함수 내에서 값이 변경되어 101이 됩니다. 변경된 값은 다시 main()으로 반환되어 101로 출력됩니다.

따라서 출력은:

| | 값은 100
함수 내의 값은 101
값은 101 |

함수 호출에 대한 더 많은 정보

포인터와의 첫 만남을 가진 후, 이제 원래 배우고자 했던 두 가지 함수 호출 유형인 값에 의한 호출과 참조에 의한 호출로 돌아가겠습니다. 일반적으로 인수는 두 가지 방법 중 하나로 함수에 전달될 수 있습니다:

| | a. 인수의 값 전송
b. 인수의 주소 전송 |

2. 값에 의한 호출

첫 번째 방법에서는 호출 함수의 각 실제 인수의 ‘값’이 호출된 함수의 해당 형식 인수에 복사됩니다. 이 방법을 사용하면 호출된 함수에서 형식 인수에 대해 수행된 변경 사항이 호출 함수의 실제 인수 값에 영향을 미치지 않습니다. 다음 프로그래밍은 값에 의한 호출을 설명합니다.

| | / 40_callbyvalue.c /
void swap( int x, int y )
int main( )
{
int a = 10, b = 20;
swap( a ,b );
printf(“\n a = %d, b = %d “, a, b);
return 0;
}
void swap( int x, int y )
{
int t;
t = x;
x = y;
y = t;
printf(“\nx = %d, y = %d”, x, y);
} |

위 프로그램의 출력은:

| | x = 20 y = 10
a = 10 b = 20 |

ab의 값은 xy의 값을 교환한 후에도 변경되지 않음을 주의하십시오.

3. 참조에 의한 호출

이번에는 호출 함수의 실제 인수 주소가 호출된 함수의 형식 인수에 복사됩니다. 이는 이러한 주소를 사용하여 실제 인수에 접근할 수 있으며, 따라서 이를 조작할 수 있음을 의미합니다. 다음 프로그램은 이 사실을 설명합니다.

| | / 41_callbyref.c /

void swap( int x, int y )

int main()
{
int a = 10, b = 20;
swap( &a, &b);
printf(“\na = %d, b = %d”, a, b);
return 0;
}

void swap( int x, int y )
{
int t;
t = x; x = y; y = t;
} |

위 프로그램의 출력은:

| | a = 20, b = 10 |

ab의 값을 교환하는 데 성공했음을 주의하십시오. xy에 저장된 주소를 사용하여. 일반적으로 C 프로그래밍에서는 값에 의한 호출을 사용합니다. 즉, 일반적으로 실제 인수를 변경할 수 없습니다. 그러나 원한다면 참조에 의한 호출을 통해 항상 이를 달성할 수 있습니다.

참조에 의한 호출을 지능적으로 사용하여

한 번에 두 개 이상의 값을 반환할 수 있는 함수를 만들 수 있습니다, 이는 일반적으로 불가능합니다. 이는 아래의 프로그램에서 보여줍니다.

| | / 42_callbyref.c /
void areaperi(int r, float a, float p)
int main()
{
int radius;
float area, perimeter;
printf(“\n원의 반지름을 입력하세요 :”); scanf(“%d”, &radius);

areaperi(radius, &area, &perimeter);

printf(“\n면적 = %f “, area);
printf(“\n둘레 = %f”, perimeter);
return 0;
}

void areaperi(int r, float a, float p)
{
a = 3.14 r r; p = 2 3.14 r;
} |

출력은 다음과 같습니다:

| | 원의 반지름 입력 5
면적 = 78.500000
둘레 = 31.400000 |

여기서 우리는 radius의 값을 전달하고 areaperimeter의 주소를 전달하고 있습니다. 주소를 전달하므로, 변수 ap에 저장된 주소의 값에서 수행하는 모든 변경은 main에서 효과를 발휘합니다. 따라서 areaperi( ) 함수에서 제어가 반환될 때 areaperimeter의 값을 출력할 수 있습니다.
따라서 호출된 함수에서 두 값을 반환할 수 있었고, 이는 한 번에 하나의 값만 반환할 수 있는 return 문을 극복한 것입니다.

VII. 지역 변수와 전역 변수

식별자의 범위에 따라 변수는 다음과 같은 유형으로 선언됩니다.

| | / 42_globalid.c /
int i=4000; / 전역 변수 선언/
int main()
{
int a=10, b=20; / 지역 변수 /
int i=100; / 지역 변수 /
printf(“%d %d”, a, b);
printf(“\n지역 i : %d”, i); / 지역 변수 접근 /
printf(“\n전역 i : %d “, ::i); / 전역 변수 접근 /
return 0;
} |

참고: 범위 해석( :: ) 연산자는 C++에서만 사용할 수 있습니다.

VIII. 저장 클래스 지정자

이 시점까지 우리는 변수 선언에 이미 익숙해졌습니다. 변수를 완전히 정의하려면 ‘유형’뿐만 아니라 ‘ 저장 클래스 ‘도 언급해야 합니다.
이 섹션에 따라 변수는 ‘데이터 유형’뿐만 아니라 ‘저장 클래스’도 가집니다.

저장 클래스는 4가지 유형이 있습니다

| | 1. 자동 저장 클래스

  1. 레지스터 저장 클래스
  2. 정적 저장 클래스
  3. 외부 저장 클래스 |

1. 자동 저장 클래스

키워드auto
저장소메모리
기본값Null
범위변수가 정의된 블록에 국한됨
생명블록 실행까지

예:

| | / 43_auto.c /
#include
int main()
{
auto int i, j;
printf(“%d %d”, i, u);
return 0;
} |

2. 레지스터 저장 클래스

키워드register
저장소CPU 레지스터
기본값Null
범위변수가 정의된 블록에 국한됨
생명블록 실행까지

예:

| | / 44_register.c /
#include
int main( )
{
register int i, j;
for(i=1;i<=10;i++)
printf(“\n%d”, i);
return 0;
} |

3. 정적 저장 클래스

키워드static
저장소메모리
기본값0
범위변수가 정의된 블록에 국한됨
생명서로 다른 함수 호출 간에 변수의 값이 지속됨

예:

| | / 45_static.c /
#include
void add();
int main()
{
add();
add();
add();
return 0;
}
void add()
{
static int i = 1;
printf(“%d\n”,i++);
} |

4. 외부 저장 클래스

키워드extern
저장소메모리
기본값0
범위전역
생명프로그램 실행이 끝나지 않는 한

예:

| | / 46_extern.c /
#include
int i;
void add(); / 외부 변수 /
int main( )
{
extern j=10; / 외부 변수 /
for(i=1;i<=10;i++)
add();
return 0;
}
void add( )
{
j++;
printf(“%d %d\n”, i, j);
} |

Share: X/Twitter LinkedIn

새 게시물을 받은 편지함에서 받기

스팸은 없습니다. 언제든지 구독 해지 가능합니다.