"정적"또는 "외부"가없는 "인라인"이 C99에서 유용합니까?
이 코드를 빌드하려고 할 때
inline void f() {}
int main()
{
f();
}
명령 줄 사용
gcc -std=c99 -o a a.c
링커 오류 (에 대한 정의되지 않은 참조 f
)가 발생합니다. 를 사용 static inline
하거나 extern inline
대신 inline
또는 컴파일 하면 오류가 사라집니다 -O
(따라서 함수는 실제로 인라인됩니다).
이 동작은 C99 표준의 단락 6.7.4 (6)에 정의 된 것으로 보입니다.
번역 단위의 함수에 대한 모든 파일 범위 선언에이
inline
없는 함수 지정자가 포함 된 경우extern
해당 번역 단위의 정의는 인라인 정의입니다. 인라인 정의는 함수에 대한 외부 정의를 제공하지 않으며 다른 번역 단위의 외부 정의를 금지하지 않습니다. 인라인 정의는 외부 정의에 대한 대안을 제공하며, 번역자가 동일한 번역 단위에서 함수에 대한 호출을 구현하는 데 사용할 수 있습니다. 함수 호출이 인라인 정의를 사용하는지 외부 정의를 사용하는지는 지정되지 않습니다.
이 모든 것을 올바르게 이해 inline
하면 위의 예제에서 정의한 함수가있는 컴파일 단위 는 동일한 이름의 외부 함수도있을 때만 일관되게 컴파일되며 내 함수 또는 외부 함수가 호출되는지 알 수 없습니다.
이 행동은 완전히 멍청하지 않습니까? C99 inline
없이 static
또는 extern
C99에서 함수를 정의하는 것이 유용 합니까? 내가 뭔가를 놓치고 있습니까?
답변 요약
물론 나는 무언가를 놓치고 있었고 행동은 멍청하지 않았습니다. :)
Nemo가 설명 했듯이 , 아이디어는 함수 의 정의 를 넣는 것 입니다.
inline void f() {}
헤더 파일과 선언 만
extern inline void f();
해당 .c 파일에서. extern
선언 만 외부에서 볼 수있는 이진 코드 생성을 트리거합니다. 그리고 실제로 inline
.c 파일 에는을 사용하지 않습니다 . 헤더에서만 유용합니다.
는 AS 조나단의 답변에 인용 된 C99위원회의 근거 해명, inline
호출의 사이트에서 볼 수 있도록 함수의 정의를 요구하는 컴파일러 최적화에 대한 모든 것입니다. 이것은 헤더에 정의를 넣어야 만 가능하며 물론 헤더의 정의는 컴파일러가 볼 때마다 코드를 내 보내지 않아야합니다. 그러나 컴파일러가 실제로 함수를 인라인하도록 강요하지 않기 때문에 외부 정의가 어딘가에 있어야합니다.
실제로이 훌륭한 답변은 귀하의 질문에 대한 답변도 제공합니다.
아이디어는 "인라인"이 헤더 파일에서 사용 된 다음 .c 파일에서 "외부 인라인"으로 사용될 수 있다는 것입니다. "extern inline"은 생성 된 코드 (외부에서 볼 수있는)를 포함해야하는 객체 파일을 컴파일러에 지시하는 방법입니다.
[정교하게 업데이트]
.c 파일에서 "인라인"( "정적"또는 "외부"없이)에 대한 사용이 없다고 생각합니다. 그러나 헤더 파일에서는 의미가 있으며 실제로 독립 실행 형 코드를 생성하려면 일부 .c 파일에 해당 "extern inline"선언이 필요합니다.
표준 (ISO / IEC 9899 : 1999) 자체에서 :
부록 J.2 정의되지 않은 동작
- ...
- 외부 연결이있는
inline
함수 는 함수 지정자로 선언 되지만 동일한 변환 단위 (6.7.4)에서도 정의되지 않습니다.- ...
C99위원회는 근거를 작성했으며 다음 과 같이 말합니다.
6.7.4 함수 지정자
C99의 새로운 기능 :
inline
C ++에서 채택 된 키워드 는 함수 선언에서만 사용할 수 있는 함수 지정자 입니다. 호출 사이트에서 볼 수있는 함수 정의가 필요한 프로그램 최적화에 유용합니다. (표준은 이러한 최적화의 특성을 지정하지 않습니다.)Visibility is assured if the function has internal linkage, or if it has external linkage and the call is in the same translation unit as the external definition. In these cases, the presence of the
inline
keyword in a declaration or definition of the function has no effect beyond indicating a preference that calls of that function should be optimized in preference to calls of other functions declared without theinline
keyword.Visibility is a problem for a call of a function with external linkage where the call is in a different translation unit from the function’s definition. In this case, the
inline
keyword allows the translation unit containing the call to also contain a local, or inline, definition of the function.A program can contain a translation unit with an external definition, a translation unit with an inline definition, and a translation unit with a declaration but no definition for a function. Calls in the latter translation unit will use the external definition as usual.
An inline definition of a function is considered to be a different definition than the external definition. If a call to some function
func
with external linkage occurs where an inline definition is visible, the behavior is the same as if the call were made to another function, say__func
, with internal linkage. A conforming program must not depend on which function is called. This is the inline model in the Standard.A conforming program must not rely on the implementation using the inline definition, nor may it rely on the implementation using the external definition. The address of a function is always the address corresponding to the external definition, but when this address is used to call the function, the inline definition might be used. Therefore, the following example might not behave as expected.
inline const char *saddr(void) { static const char name[] = "saddr"; return name; } int compare_name(void) { return saddr() == saddr(); // unspecified behavior }
Since the implementation might use the inline definition for one of the calls to
saddr
and use the external definition for the other, the equality operation is not guaranteed to evaluate to 1 (true). This shows that static objects defined within the inline definition are distinct from their corresponding object in the external definition. This motivated the constraint against even defining a non-const
object of this type.Inlining was added to the Standard in such a way that it can be implemented with existing linker technology, and a subset of C99 inlining is compatible with C++. This was achieved by requiring that exactly one translation unit containing the definition of an inline function be specified as the one that provides the external definition for the function. Because that specification consists simply of a declaration that either lacks the
inline
keyword, or contains bothinline
andextern
, it will also be accepted by a C++ translator.Inlining in C99 does extend the C++ specification in two ways. First, if a function is declared
inline
in one translation unit, it need not be declaredinline
in every other translation unit. This allows, for example, a library function that is to be inlined within the library but available only through an external definition elsewhere. The alternative of using a wrapper function for the external function requires an additional name; and it may also adversely impact performance if a translator does not actually do inline substitution.Second, the requirement that all definitions of an inline function be “exactly the same” is replaced by the requirement that the behavior of the program should not depend on whether a call is implemented with a visible inline definition, or the external definition, of a function. This allows an inline definition to be specialized for its use within a particular translation unit. For example, the external definition of a library function might include some argument validation that is not needed for calls made from other functions in the same library. These extensions do offer some advantages; and programmers who are concerned about compatibility can simply abide by the stricter C++ rules.
Note that it is not appropriate for implementations to provide inline definitions of standard library functions in the standard headers because this can break some legacy code that redeclares standard library functions after including their headers. The
inline
keyword is intended only to provide users with a portable way to suggest inlining of functions. Because the standard headers need not be portable, implementations have other options along the lines of:#define abs(x) __builtin_abs(x)
or other non-portable mechanisms for inlining standard library functions.
> I get a linker error (undefined reference to f
)
Works here: Linux x86-64, GCC 4.1.2. May be a bug in your compiler; I don't see anything in the cited paragraph from the standard that forbids the given program. Note the use of if rather than iff.
An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit.
So, if you know the behavior of the function f
and you want to call it in a tight loop, you may copy-paste its definition into a module to prevent function calls; or, you may provide a definition that, for the purposes of the current module, is equivalent (but skips input validation, or whatever optimization you can imagine). The compiler writer, however, has the option of optimizing for program size instead.
참고URL : https://stackoverflow.com/questions/6312597/is-inline-without-static-or-extern-ever-useful-in-c99
'code' 카테고리의 다른 글
자동으로 모든 함수에 console.log 추가 (0) | 2020.09.06 |
---|---|
파일이 있는지 확인하지만 콘솔에 404 오류가 표시되지 않도록합니다. (0) | 2020.09.06 |
실행하지 않고 Eclipse에서 Java 프로그램을 컴파일하려면 어떻게해야합니까? (0) | 2020.09.06 |
HTML5 Boilerplate 및 Twitter 부트 스트랩 (0) | 2020.09.06 |
콘솔 애플리케이션의 신뢰할 수있는 타이머 (0) | 2020.09.06 |