Function declarations
함수 선언은 함수를 지정하는 식별자 를 도입하고, 선택적으로 함수 매개변수의 타입들( 프로토타입 )을 명시합니다. 함수 선언은( 정의 와 달리) 파일 범위뿐만 아니라 블록 범위에서도 나타날 수 있습니다.
목차 |
구문
함수 선언의 선언 문법 에서, type-specifier 시퀀스(선언자에 의해 수정될 수 있음)는 반환 타입 (배열이나 함수 타입이 아닌 모든 타입일 수 있음)을 지정하며, declarator 는 다음 세 가지 (C23 이전) 두 가지 (C23 이후) 형태 중 하나를 가집니다:
noptr-declarator
(
parameter-list
)
attr-spec-seq
(선택적)
|
(1) | ||||||||
noptr-declarator
(
identifier-list
)
attr-spec-seq
(선택적)
|
(2) | (C23 이전) | |||||||
noptr-declarator
(
)
attr-spec-seq
(선택적)
|
(3) | ||||||||
여기서
| noptr-declarator | - | 괄호로 묶이지 않은 포인터 선언자를 제외한 모든 declarator . 이 선언자에 포함된 식별자가 함수 지정자(function designator)가 되는 식별자입니다. |
| parameter-list | - | 단일 키워드 void 또는 쉼표로 구분된 매개변수 목록이며, 생략 매개변수(ellipsis parameter) 로 끝날 수 있습니다. |
| identifier-list | - | 쉼표로 구분된 식별자 목록으로, 이 선언자가 구형 스타일 함수 정의(function definition) 의 일부로 사용될 때만 가능합니다. |
| attr-spec-seq | - | (C23) 함수 타입에 적용되는 속성(attributes) 의 선택적 목록 |
int max(int a, int b); // declaration int n = max(12.01, 3.14); // OK, conversion from double to int
int max(a, b) int a, b; // definition expects ints; the second call is undefined { return a > b ? a : b; } int n = max(true, (char)'a'); // calls max with two int args (after promotions) int n = max(12.01f, 3.14); // calls max with two double args (after promotions)
설명
함수의 반환 유형은 specifiers-and-qualifiers 에 있는 타입 지정자에 의해 결정되며, 일반적인 declarations 에서처럼 declarator 에 의해 수정될 수 있습니다. 이는 배열이 아닌 객체 타입이거나 void 타입이어야 합니다. 함수 선언이 정의가 아닌 경우, 반환 타입은 incomplete 일 수 있습니다. 반환 타입은 cvr-qualified가 될 수 없습니다: 모든 qualified 반환 타입은 함수 타입을 구성하기 위해 unqualified 버전으로 조정됩니다.
void f(char *s); // 반환 타입은 void int sum(int a, int b); // sum의 반환 타입은 int int (*foo(const void *p))[3]; // 반환 타입은 3개 int 배열에 대한 포인터 double const bar(void); // double(void) 타입 함수 선언 double (*barp)(void) = bar; // OK: barp는 double(void)에 대한 포인터 double const (*barpc)(void) = barp; // OK: barpc 또한 double(void)에 대한 포인터
함수 선언자는 자신의 타입 지정자와 한정자를 공유할 수 있는 한 다른 선언자와 결합될 수 있습니다
int f(void), *fip(), (*pfi)(), *ap[3]; // 두 개의 함수와 두 개의 객체를 선언합니다 inline int g(int), n; // 오류: inline 한정자는 함수에만 사용할 수 있습니다 typedef int array_t[3]; array_t a, h(); // 오류: 배열 타입은 함수의 반환 타입이 될 수 없습니다
함수 선언이 어떤 함수 외부에 나타나면, 그것이 도입하는 식별자는 파일 범위 와 외부 링크 를 가지며, static 이 사용되거나 이전의 정적 선언이 보이는 경우를 제외합니다. 선언이 다른 함수 내부에서 발생하면, 식별자는 블록 범위(그리고 또한 내부 또는 외부 링크)를 가집니다.
int main(void) { int f(int); // 외부 링크, 블록 범위 f(1); // 정의는 프로그램 내 어딘가에서 사용 가능해야 함 }
함수 정의의 일부가 아닌 선언에서의 매개변수들은 이름을 지정할 필요가 없습니다: function definition (until C23)
int f(int, int); // 선언 // int f(int, int) { return 7; } // 오류: 정의에서는 매개변수 이름을 지정해야 함 // 이 정의는 C23부터 허용됨
매개변수 목록의 각 매개변수는 parameter-list 단일 변수를 도입하는 선언 으로, 다음과 같은 추가 속성을 가집니다:
- 선언자 내 식별자는 선택 사항입니다 (단, 이 함수 선언이 함수 정의의 일부인 경우는 제외) (until C23)
int f(int, double); // OK int g(int a, double b); // 역시 OK // int f(int, double) { return 1; } // 오류: 정의에서는 매개변수 이름을 지정해야 함 // 이 정의는 C23부터 허용됨
- 매개변수에 허용되는 유일한 저장 클래스 지정자 는 register 이며, 정의가 아닌 함수 선언에서는 무시됩니다
int f(static int x); // 오류 int f(int [static 10]); // OK (배열 인덱스 static은 저장 클래스 지정자가 아님)
- 배열 타입의 모든 매개변수는 해당 포인터 타입으로 조정됩니다 , 배열 선언자의 대괄호 사이에 한정자가 있는 경우 한정될 수 있습니다 (since C99)
int f(int[]); // int f(int*)를 선언합니다 int g(const int[10]); // int g(const int*)를 선언합니다 int h(int[const volatile]); // int h(int * const volatile)를 선언합니다 int x(int[*]); // int x(int*)를 선언합니다
- 함수 타입의 매개변수는 해당 포인터 타입으로 조정됩니다
int f(char g(double)); // int f(char (*g)(double))를 선언합니다 int h(int(void)); // int h(int (*)(void))를 선언합니다
-
매개변수 목록은
, ...로 끝나거나...(C23부터) 일 수 있습니다. 자세한 내용은 가변 인자 함수 를 참조하십시오.
int f(int, ...);
- 매개변수는 void 타입을 가질 수 없습니다(하지만 void 포인터 타입은 가질 수 있습니다). void 키워드로만 구성된 특별한 매개변수 목록은 매개변수를 받지 않는 함수를 선언하는 데 사용됩니다.
int f(void); // 정상 int g(void x); // 오류
- 매개변수 목록에 나타나는 식별자 중 typedef 이름 또는 매개변수 이름으로 처리될 수 있는 것은 typedef 이름으로 처리됩니다: int f ( size_t , uintptr_t ) 는 size_t 와 uintptr_t 타입의 이름 없는 두 매개변수를 취하는 함수에 대한 새로운 스타일 선언자로 파싱되며, " size_t "와 " uintptr_t "라는 이름의 두 매개변수를 취하는 함수 정의를 시작하는 구식 스타일 선언자가 아닙니다.
- 매개변수는 불완전한 타입을 가질 수 있으며 VLA 표기법을 사용할 수 있습니다 [ * ] (C99부터) (단, 함수 정의 에서는 배열-대-포인터 및 함수-대-포인터 조정 이후의 매개변수 타입이 완전해야 합니다).
|
속성 지정자 시퀀스 는 함수 매개변수에도 적용할 수 있습니다. |
(C23부터) |
함수 호출의 세부 메커니즘에 대해서는 function call operator 를 참조하고, 함수에서 반환하는 방법에 대해서는 return 을 참조하십시오.
참고 사항
|
C++와 달리, 선언자 f ( ) 와 f ( void ) 는 서로 다른 의미를 가집니다: 선언자 f ( void ) 는 매개변수를 받지 않는 함수를 선언하는 새로운 스타일(프로토타입) 선언자입니다. 선언자 f ( ) 는 지정되지 않은 수의 매개변수를 받는 함수를 선언하는 선언자입니다(함수 정의에서 사용되는 경우 제외). int f(void); // declaration: takes no parameters int g(); // declaration: takes unknown parameters int main(void) { f(1); // compile-time error g(2); // undefined behavior } int f(void) { return 1; } // actual definition int g(a,b,c,d) int a,b,c,d; { return 2; } // actual definition |
(C23 이전) |
함수 정의 와 달리, 매개변수 목록은 typedef에서 상속될 수 있습니다
typedef int p(int q, int r); // p는 함수 타입 int(int, int)입니다 p f; // int f(int, int)를 선언합니다
|
C89에서는, specifiers-and-qualifiers 가 선택 사항이었으며, 생략할 경우 함수의 반환 타입은 기본적으로 int 가 되었습니다( declarator 에 의해 수정될 수 있음). *f() { // function returning int* return NULL; } |
(until C99) |
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| DR 423 | C89 | 반환 타입이 한정될 수 있음 | 반환 타입은 암묵적으로 한정이 제거됨 |
참고문헌
- C23 표준 (ISO/IEC 9899:2024):
-
- 6.7.7.4 함수 선언자 (프로토타입 포함) (p: 130-132)
- C17 표준 (ISO/IEC 9899:2018):
-
- 6.7.6.3 함수 선언자 (프로토타입 포함) (p: 96-98)
- C11 표준 (ISO/IEC 9899:2011):
-
- 6.7.6.3 함수 선언자 (프로토타입 포함) (p: 133-136)
- C99 표준 (ISO/IEC 9899:1999):
-
- 6.7.5.3 함수 선언자 (프로토타입 포함) (p: 118-121)
- C89/C90 표준 (ISO/IEC 9899:1990):
-
- 3.5.4.3 함수 선언자 (프로토타입 포함)
참고 항목
|
C++ documentation
for
Function declaration
|