나는 inline
그 자체로 컴파일러에 대한 제안이며, 재량에 따라 함수를 인라인 할 수도 있고 아닐 수도 있으며 링크 가능한 개체 코드도 생성 할 수 있음을 이해합니다.
나는 그것이 똑같을 것이라고 생각합니다 static inline
(인라인 될 수도 있고 아닐 수도 있습니다). 그러나 인라인 될 때 링크 가능한 객체 코드를 생성하지 않을 것입니다 (다른 모듈이 그것에 링크 할 수 없기 때문에).
그림에서 어디에 extern inline
적합합니까?
(이것은 사용하기 때문에, 예를 들어, 내가 인라인 함수에 의해 전 처리기 매크로를 교체하려면이 기능이 인라인 도착해야 가정 __FILE__
및 __LINE__
발신자에 대한 해결하지만이 호출 된 함수해야 매크로). 즉, 함수가 인라인되지 않는 경우 컴파일러 또는 링커 오류를보고 싶습니다. 않습니다 extern inline
이 작업을 수행? (그렇지 않으면 매크로를 고수하는 것 외에는이 동작을 수행 할 방법이 없다고 가정합니다.)
C ++와 C간에 차이점이 있습니까?
다른 컴파일러 공급 업체와 버전간에 차이점이 있습니까?
답변
K & R C 또는 C89에서 인라인은 언어의 일부가 아닙니다. 많은 컴파일러가이를 확장으로 구현했지만 작동 방식에 대한 정의 된 의미가 없습니다. GCC는 인라인 구현 가장 먼저이고, 도입 inline
, static inline
및 extern inline
구성하는 단계; 대부분의 C99 이전 컴파일러는 일반적으로 그 선두를 따릅니다.
GNU89 :
inline
: 함수는 인라인 될 수 있습니다 (단지 힌트 일뿐입니다). 라인 외부 버전은 항상 내보내지고 외부에서 볼 수 있습니다. 따라서 이러한 인라인은 하나의 컴파일 단위에서만 정의 할 수 있으며 다른 모든 사용자는이를 라인 외부 함수로 볼 필요가 있습니다 (또는 링크 타임에 중복 기호가 표시됨).extern inline
라인 외부 버전을 생성하지 않지만 하나를 호출 할 수 있습니다 (따라서 다른 컴파일 단위에서 정의해야합니다. 그러나 단일 정의 규칙이 적용됩니다. 라인 외부 버전은 컴파일러가 대신 호출하는 경우 여기에 인라인이 제공됩니다.static inline
파일 정적 버전을 생성 할 수는 있지만 외부에서 볼 수있는 라인 외부 버전을 생성하지 않습니다. 내 보낸 외부 심볼이나 호출이 없기 때문에 단일 정의 규칙이 적용되지 않습니다.
C99 (또는 GNU99) :
inline
: GNU89 “extern inline”처럼; 외부에서 볼 수있는 함수는 생성되지 않지만 하나가 호출 될 수 있으므로 존재해야합니다.extern inline
: GNU89 “inline”처럼 : 외부에서 볼 수있는 코드가 방출되므로 최대 하나의 번역 유닛이 이것을 사용할 수 있습니다.static inline
: GNU89 “정적 인라인”과 같습니다. 이것은 gnu89와 c99 사이의 유일한 휴대용 제품입니다.
C ++ :
어디에서나 인라인 된 함수는 동일한 정의로 모든 곳에서 인라인되어야합니다. 컴파일러 / 링커는 심볼의 여러 인스턴스를 정렬합니다. static inline
또는에 대한 정의는 extern inline
없지만 많은 컴파일러가이를 가지고 있지만 (일반적으로 gnu89 모델을 따릅니다).
답변
이 진술을 기반으로 __FILE__ 및 __LINE__을 오해하고 있다고 생각합니다.
호출자에 대해 해결해야하지만 호출 된 함수가 아닌 __FILE__ 및 __LINE__ 매크로를 사용하기 때문입니다.
컴파일에는 여러 단계가 있으며 전처리가 첫 번째 단계입니다. __FILE__ 및 __LINE__은 해당 단계에서 대체됩니다. 따라서 컴파일러는 이미 대체 된 인라인 함수를 고려할 수 있습니다.
답변
다음과 같이 작성하려는 것 같습니다.
inline void printLocation()
{
cout <<"You're at " __FILE__ ", line number" __LINE__;
}
{
...
printLocation();
...
printLocation();
...
printLocation();
매번 다른 값이 인쇄되기를 바랍니다. Don이 말했듯이 __FILE__ 및 __LINE__은 전처리기에 의해 구현되지만 인라인은 컴파일러에 의해 구현되기 때문에 그렇지 않습니다. 따라서 어디서 printLocation을 호출하든 동일한 결과를 얻을 수 있습니다.
이 작업을 수행 할 수 있는 유일한 방법은 printLocation을 매크로로 만드는 것입니다. (예, 알아요 …)
#define PRINT_LOCATION {cout <<"You're at " __FILE__ ", line number" __LINE__}
...
PRINT_LOCATION;
...
PRINT_LOCATION;
...
답변
답변
여기서 매크로는 인라인 함수가 아닌 선택입니다. 매크로가 인라인 함수를 지배하는 드문 경우입니다. 다음을 시도해보십시오.이 “MACRO MAGIC”코드를 작성했는데 제대로 작동합니다! gcc / g ++ Ubuntu 10.04에서 테스트 됨
//(c) 2012 enthusiasticgeek (LOGGING example for StackOverflow)
#ifdef __cplusplus
#include <cstdio>
#include <cstring>
#else
#include <stdio.h>
#include <string.h>
#endif
//=========== MACRO MAGIC BEGINS ============
//Trim full file path
#define __SFILE__ (strrchr(__FILE__,'/') ? strrchr(__FILE__,'/')+1 : __FILE__ )
#define STRINGIFY_N(x) #x
#define TOSTRING_N(x) STRINGIFY_N(x)
#define _LINE (TOSTRING_N(__LINE__))
#define LOG(x, s...) printf("(%s:%s:%s)" x "\n" , __SFILE__, __func__, _LINE, ## s);
//=========== MACRO MAGIC ENDS ============
int main (int argc, char** argv) {
LOG("Greetings StackOverflow! - from enthusiasticgeek\n");
return 0;
}
여러 파일의 경우 각 c / cc / cxx / cpp 파일에 동일한 내용을 포함하여 별도의 헤더 파일에 이러한 매크로를 정의합니다. 가능한 경우 매크로보다 인라인 함수 또는 const 식별자 (필요한 경우)를 선호하십시오.
답변
“무엇을하나요?”라고 대답하는 대신 “내가 원하는 것을 어떻게 할 수 있습니까?”라고 대답합니다. 5 가지 종류의 인라인이 있으며 모두 GNU C89, 표준 C99 및 C ++에서 사용할 수 있습니다.
주소를 사용하지 않는 한 항상 인라인
__attribute__((always_inline))
선언에 추가 한 다음 아래 사례 중 하나를 사용하여 주소를 가져올 가능성을 처리하십시오.
의미론이 필요하지 않은 경우 (예 : 특정 방식으로 어셈블리에 영향을 미치거나를 사용하기 위해 alloca
) 이것을 사용해서는 안됩니다 . 컴파일러는 일반적으로 그만한 가치가 있는지 당신보다 더 잘 알고 있습니다.
인라인하고 약한 기호를 내 보냅니다 (예 : C ++, 일명 “그냥 작동하게”).
__attribute__((weak))
void foo(void);
inline void foo(void) { ... }
이렇게하면 동일한 코드의 복사본이 여러 개 남고 링커는 임의로 하나를 선택합니다.
인라인, 그러나 어떤 기호도 방출하지 않음 (외부 참조 남김)
__attribute__((gnu_inline))
extern inline void foo(void) { ... }
항상 방출 (하나의 TU에 대해 이전 문제 해결)
힌트 된 버전은 C ++에서 약한 기호를 내 보냅니다. 그러나 C의 어느 방언에서나 강한 기호를 내 보냅니다.
void foo(void);
inline void foo(void) { ... }
또는 두 언어 모두에서 강력한 기호를 표시하는 힌트없이 수행 할 수 있습니다.
void foo(void) { ... }
일반적으로 정의를 제공 할 때 TU가 어떤 언어인지 알고 있으며 인라인이 많이 필요하지 않을 수 있습니다.
모든 TU에서 인라인 및 방출
static inline void foo(void) { ... }
static
하나를 제외한 모든 항목에 대해 void foo(void)
위에 선언을 추가 할 수 있습니다 . 이것은 깨끗한 헤더를 작성한 다음 #include
인라인 정의가있는 별도의 파일 을 작성하는 “모범 사례”에 도움이됩니다 . 그런 다음 C 스타일 인라인을 사용하는 경우 #define
하나의 전용 TU에서 다른 매크로를 사용하여 라인 외부 정의를 제공합니다.
extern "C"
헤더가 C와 C ++ 모두에서 사용될 수 있는지 잊지 마세요 !