Clang 확장을 이용한 C 함수 오버로딩

C++와 같은 함수 오버로딩을 Clang의 언어 확장을 통해 C언어에서 사용할 수 있다. 자료형이나 추가 인자에 따라 여러가지 변형으로 반복되는 함수들을 다룰 때 유용하다. 아래와 같이 함수의 선언과 정의에 각각 overloadable 속성을 지정한다. 선언과 정의가 일치하지 않으면 함수의 시그니처가 달라지므로 문제가 된다.

__attribute__((overloadable)) void f(void);
__attribute__((overloadable)) void f(int i);
__attribute__((overloadable)) void f(int i, int j);

__attribute__((overloadable)) void f(void) { /* ... */ }
__attribute__((overloadable)) void f(int i) { /* ... */ }
__attribute__((overloadable)) void f(int i, int j) { /* ... */ }

overloadable 속성을 가진 함수가 void 형 인자를 취할 경우에는 선언에서 void를 생략할 수 없다. C++와 달리, C언어 표준에서 빈 인자목록을 가진 선언은 인자의 프로토타입 정보가 없는 선언이 된다. 이 선언만으로는 어떤 인자를 넣어 호출해도 컴파일된다. 정의에서 생략하는 것은 void 형 인자를 가지는 것(인자가 없는 것)과 같은 의미이다.

__attribute__((overloadable)) void f(void);
__attribute__((overloadable)) void f() { /* OK */ }

Clang에서는 이러한 함수들을 C++ name mangling1과 같은 방법으로 시그니처(심볼)을 생성한다. nm을 통하여 아래와 같이 확인할 수 있다.

$ clang -c overloadable.c
$ nm overloadable.o               
0000000000000010 T __Z1fi  # f(int)
0000000000000020 T __Z1fii # f(int, int)
0000000000000000 T __Z1fv  # f(void)

애플의 simd 프레임웍2에서 선형대수학 함수들에서 사용되고 있다. 스위프트에서도 이 함수들을 호출할 수 있다. 2013년 출시한 Clang 3.3 즈음에 overloadable 속성이 추가된 것으로 보아, 2014년에 출시한 OS X 10.10 Yosemite에서 추가된 simd 프레임웍에서 사용하기 위해 만들어진 것으로 생각된다. 더 자세한 내용은 Clang 문서에서 확인할 수 있다.


  1. Name mangling (Wikipedia) ↩︎

  2. simd ↩︎