Quick Syntax
함수는 값을 계산하거나 동작을 수행합니다. C에서는 선언, 정의, 호출과 함께 값을 복사하는 기본 전달 방식을 먼저 구분하면 됩니다.
c
#include <stdio.h>
/* 선언(prototype): 다른 위치에서 호출하기 전에 시그니처를 알린다. */
int max_of(int a, int b);
void print_ready(void);
int divide(int a, int b, int *q);
/* 정의: 선언과 같은 시그니처로 본문을 제공한다. */
int max_of(int a, int b) {
return (a > b) ? a : b;
}
void print_ready(void) {
puts("ready");
}
int divide(int a, int b, int *q) {
if (b == 0 || q == NULL) return 0;
*q = a / b;
return 1;
}
int main(void) {
int left = 10;
int right = 20;
int quotient;
int best = max_of(left, right); /* 호출 */
if (divide(left, right, "ient)) {
printf("best=%d, quotient=%d\n", best, quotient);
}
print_ready();
return 0;
}계산 결과 하나면 반환값을, 호출자에게 여러 결과를 써야 하면 포인터 매개변수를 씁니다. f()가 아니라 f(void)가 매개변수가 없다는 완전한 C 함수 선언입니다.
문법
함수는 반환형, 이름, 매개변수 목록, 본문으로 읽습니다. 정의보다 먼저 호출하거나 다른 파일에서 호출할 함수라면, 호출 전에 같은 시그니처의 원형을 보이게 해야 합니다.
c
#include <stdio.h>
int max_of(int a, int b); // 선언
int max_of(int a, int b) { // 정의
return (a > b) ? a : b;
}
void print_ready(void) {
puts("ready");
}매개변수가 없는 함수는 새 코드에서 f(void) 형태로 씁니다. C17 이전의 f() 선언은 인자 정보가 없는 선언이었고, C23에서는 함수 정의 밖의 빈 매개변수 목록이 제약 위반입니다. f(void)는 이 차이를 피하면서 인자가 없음을 분명히 합니다.
전달과 결과
일반 인자는 값이 복사됩니다. 함수 안에서 a나 b를 바꿔도 호출자 변수는 바뀌지 않습니다. 호출자의 값을 바꾸거나 결과를 여러 개 돌려줘야 할 때만 포인터를 사용합니다.
c
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
bool divide(int a, int b, int *q, int *r) {
if (b == 0 || q == NULL || r == NULL) {
return false;
}
*q = a / b;
*r = a % b;
return true;
}
int q = 0;
int r = 0;
if (divide(10, 3, &q, &r)) {
printf("%d ... %d\n", q, r);
}- 결과 하나가 주된 답이면 반환값을 먼저 봅니다.
- 호출자 상태를 수정하거나 결과 여러 개가 필요하면 출력 포인터를 씁니다.
- 포인터 인자는 읽기만 하면
const T *, 수정하면T *로 의도를 드러냅니다. - 출력 포인터를 받는 함수는 NULL 허용 여부와 실패했을 때 값을 바꾸는지를 계약으로 정합니다.
주의할 점
- 선언과 정의의 반환형·인자 타입이 다르면 호출 규약이 어긋납니다.
- 값을 반환하는 함수는 사용되는 모든 경로에서 값을 반환해야 합니다.
- 큰 구조체를 값으로 넘기면 복사가 일어납니다. 읽기만 한다면
const struct T *를 검토합니다. assert나 조건식 안에 호출 결과를 숨기지 말고, 실패를 호출자에게 어떻게 전달할지 먼저 정합니다.
참고 링크
2 sources