Programing

"정적"이나 "외부"가 없는 "인라인"이 C99에서 유용할 수 있는가?

c10106 2022. 4. 24. 10:19
반응형

"정적"이나 "외부"가 없는 "인라인"이 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위의 예에서와 같이 이름이 같은 외부 기능도 있는 경우에만 일관성 있게 컴파일하고, 나 자신의 기능이나 외부 기능이 호출되는지는 결코 알 수 없다.

이 행동은 완전히 어리석지 않은가?함수를 정의하는 것이 유용한가?inlinestatic또는externC99에? 가 뭐 거 있어내가 뭘 빼놓았나요?

답변 요약

물론 나는 뭔가를 놓치고 있었고, 그 행동은 어리석지 않았다.:)

니모의 설명대로 함수의 정의를 넣자는 것이다.

inline void f() {}

머리글 파일에 선언만 있을 뿐

extern inline void f();

해당 .c 파일에.오직 더extern선언은 외부에서 볼 수 있는 이진 코드의 생성을 촉발한다.그리고 정말로 아무 소용이 없다.inline로 -- c 파일로, 머리글에서만 유용하게 쓰일 수 있다.

조나단의 답변에서 인용한 C99 위원회의 이론이 설명하듯이,inline함수의 정의를 호출 부위에서 볼 수 있어야 하는 컴파일러 최적화에 관한 모든 것이다.이는 헤더에 정의를 넣어야만 달성할 수 있으며, 물론 헤더에 있는 정의는 컴파일러가 볼 때마다 코드를 내보내지 않아야 한다.그러나 컴파일러는 실제로 함수를 인라인으로 연결하도록 강요되지 않기 때문에, 외부 정의가 어딘가에 존재해야 한다.

사실 이 훌륭한 대답은 또한 당신의 질문에 대답할 수 있다고 생각한다.

외부 인라인에서 하는 일은?

헤더 파일에서는 "인라인"을, 그리고 .c 파일에서는 "외부 인라인"을 사용할 수 있다는 생각이다."외부 인라인"은 컴파일러에게 어떤 객체 파일이 생성되는 코드를 포함해야 하는지 지시하는 방법이다.

[업데이트, 자세히 설명하기 위해

.c 파일에서 ("정적" 또는 "외부"가 없는) 인라인"에는 어떤 용도가 없다고 생각한다.그러나 헤더 파일에서는 타당하며, 실제로 독립 실행형 코드를 생성하기 위해서는 일부 .c 파일에 해당하는 "외부 인라인" 선언이 필요하다.

표준(ISO/IEC 9899:1999) 자체에서 다음과 같이 한다.

부록 J.2 정의되지 않은 동작

  • ...
  • 외부 연결이 있는 함수는 다음과 같이 선언된다.inline함수 지정자(function specifier)는 동일 번역 단위(6.7.4)에서도 정의되지 않는다.
  • ...

C99 위원회는 근거를 썼으며, 다음과 같이 말하고 있다.

6.7.4 기능 지정자

C99의 새로운 기능:inlineC++에서 채택된 키워드는 함수 선언에서만 사용할 수 있는 함수 지정자다.함수의 정의를 통화 현장에서 볼 수 있어야 하는 프로그램 최적화에 유용하다. (이 기준서는 이러한 최적화의 성격을 규정하려고 하지 않는다는 점에 유의한다.)

함수에 내부 연계가 있거나, 외부 연계가 있고 통화가 외부 정의와 동일한 번역 단위에 있는 경우 가시성이 보장된다.이런 경우, 그 존재는 그 사람의 존재에 의해 결정된다.inline함수의 선언이나 정의에서 키워드는 해당 함수의 호출을 명령 없이 선언된 다른 함수의 호보다 우선하여 최적화해야 한다는 선호를 나타내는 것 이상의 효과는 없다.inline키워드

가시성은 호가 함수의 정의와 다른 번역 단위에 있는 외부 연계를 가진 함수의 호출에 대한 문제다. 이우 .inline키워드는 통화가 포함된 번역 단위가 함수의 로컬 또는 인라인 정의도 포함할 수 있도록 한다.

프로그램에는 외부 정의의 번역 단위, 인라인 정의의 번역 단위, 선언이 있지만 함수에 대한 정의가 없는 번역 단위가 포함될 수 있다.후자번역단위의 호출은 평상시처럼 외부 정의를 사용한다.

함수의 인라인 정의는 외부 정의와 다른 정의로 간주된다.어떤 기능을 호출할 경우func인라인 정의가 보이는 곳에서 외부 연결이 일어나면, 그 동작은 마치 다른 기능으로 통화가 이루어진 것과 같다.__func 연계가 내부로.적합한 프로그램은 어떤 기능을 호출하느냐에 따라 결정되어서는 안 된다.이것은 표준의 인라인 모델이다.

적합한 프로그램은 인라인 정의를 사용한 구현에 의존해서는 안 되며, 외부 정의를 사용한 구현에 의존해서는 안 된다.함수의 주소는 항상 외부 정의에 해당하는 주소지만, 함수를 호출하기 위해 이 주소를 사용할 경우 인라인 정의가 사용될 수 있다.따라서 다음의 예는 예상대로 행동하지 않을 수 있다.

inline const char *saddr(void)
{
    static const char name[] = "saddr";
    return name;
}
int compare_name(void)
{
    return saddr() == saddr(); // unspecified behavior
}

구현 시 다음 호출 중 하나에 인라인 정의를 사용할 수 있으므로saddr그리고 다른 정의에 대해 외부 정의를 사용한다. 평등 연산은 1까지 평가하도록 보장되지 않는다(참).이것은 인라인 정의 내에서 정의된 정적 객체가 외부 정의에서 해당 객체와 구별됨을 보여준다.const이런 종류의 물건

인라이닝은 기존 링커 기술로 구현할 수 있는 방식으로 이 표준에 추가되었으며, 인라이닝의 일부 C99는 C++와 호환된다.이것은 인라인 함수의 정의를 포함하는 정확히 하나의 번역 단위를 함수의 외부 정의를 제공하는 단위로 명시하도록 요구함으로써 달성되었다.왜냐하면 그 명세서는 단순히 두 가지 중 하나가 없는 선언으로 구성되어 있기 때문이다.inline키워드 또는 둘 다 포함inline그리고extern, 또한 C++ 번역가에게 받아들여질 것이다.

C99의 인라이닝은 두 가지 방법으로 C++ 사양을 확장한다.첫째, 함수가 선언된 경우inline하나의 번역 단위로, 그것은 선언될 필요가 없다.inline할 수 있는 을 예로 들 수 예를 들어, 이것은 라이브러리 내에 삽입되어야 하지만 다른 곳에서 외부 정의를 통해서만 사용할 수 있는 라이브러리 함수를 허용한다.외부 기능에 래퍼 함수를 사용하는 대안으로 추가 이름이 필요하며, 번역기가 실제로 인라인 대체를 하지 않을 경우 성능에 부정적인 영향을 미칠 수도 있다.

둘째, 인라인 함수의 모든 정의를 "정확히 동일"해야 한다는 요구사항은 프로그램의 동작이 어떤 함수의 가시적인 인라인 정의 또는 외부 정의로 구현되는지에 따라 달라지지 않아야 한다는 요구사항으로 대체된다.이것은 인라인 정의가 특정 번역 단위 내에서 그 사용에 특화되도록 한다.예를 들어, 라이브러리 함수의 외부 정의에는 동일한 라이브러리의 다른 함수에서 걸려온 호출에 필요하지 않은 일부 인수 유효성 검사가 포함될 수 있다.이러한 확장은 몇 가지 장점을 제공한다; 호환성에 대해 우려하는 프로그래머들은 단지 더 엄격한 C++ 규칙을 준수할 수 있다.

표준 헤더에서 표준 라이브러리 기능의 인라인 정의를 제공하는 것은 구현에 적합하지 않다는 점에 유의하십시오. 이는 헤더를 포함한 후 표준 라이브러리 기능을 다시 표시하는 일부 레거시 코드를 손상시킬 수 있기 때문이다.inline키워드는 사용자에게 기능의 개요를 제안할 수 있는 휴대용 방법을 제공하기 위한 것이다.표준 헤더는 휴대할 필요가 없으므로, 구현에는 다음과 같은 다른 옵션이 있다.

#define abs(x) __builtin_abs(x)

또는 표준 라이브러리 기능의 개요를 위한 기타 비휴대용 메커니즘.

> 링커 오류(미정의 참조)가 발생함f)

여기서 작동: Linux x86-64, GCC 4.1.2당신의 컴파일러에서 버그가 될 수도 있다; 나는 주어진 프로그램을 금지하는 기준에서 인용된 단락의 어떤 것도 보지 못한다.iff가 아닌 if의 사용에 유의하십시오.

인라인 정의는 외부 정의에 대한 대안을 제공하며, 번역자는 동일한 번역 단위의 함수에 대한 호출을 구현하기 위해 사용할 수 있다.

그래서, 만약 당신이 그 함수의 행동을 안다면f그리고 당신은 그것을 긴밀하게 부르기를 원하거나, 당신은 기능 호출을 막기 위해 그것의 정의를 모듈에 복사하거나, 또는 당신은 현재 모듈의 목적상 동등한 정의를 제공할 수 있다.그러나 컴파일러 작성자는 대신 프로그램 크기에 맞게 최적화할 수 있는 옵션이 있다.

참조URL: https://stackoverflow.com/questions/6312597/is-inline-without-static-or-extern-ever-useful-in-c99

반응형