IT이야기

재귀 함수를 인라인으로 할 수 있습니까?

cyworld 2022. 6. 19. 18:29
반응형

재귀 함수를 인라인으로 할 수 있습니까?

inline int factorial(int n)
{
    if(!n) return 1;
    else return n*factorial(n-1);
}

이것을 읽고 있는 중에, 위의 코드가 컴파일러에 의해서 올바르게 처리되지 않으면 「무한 컴파일」이 되는 것을 알았습니다.

컴파일러는 함수를 인라인화할지 여부를 어떻게 결정합니까?

, ★★★★★★★★★★★★★★.inline함수의 사양은 힌트에 불과합니다.는, 「」(의 유무를 할 수 .inline한정자이와 같이 컴파일러는 무한 루프를 풀 수 있는 만큼 재귀 함수를 인라인화할 수 있습니다.기능을 「언롤」하는 레벨에 제한을 두는 것만으로 끝납니다.

최적화 컴파일러는 다음 코드를 돌릴 수 있습니다.

inline int factorial(int n)
{
    if (n <= 1)
    {
        return 1;
    }
    else
    {
        return n * factorial(n - 1);
    }
}

int f(int x)
{
    return factorial(x);
}

다음 코드에 입력합니다.

int factorial(int n)
{
    if (n <= 1)
    {
        return 1;
    }
    else
    {
        return n * factorial(n - 1);
    }
}

int f(int x)
{
    if (x <= 1)
    {
        return 1;
    }
    else
    {
        int x2 = x - 1;
        if (x2 <= 1)
        {
            return x * 1;
        }
        else
        {
            int x3 = x2 - 1;
            if (x3 <= 1)
            {
                return x * x2 * 1;
            }
            else
            {
                return x * x2 * x3 * factorial(x3 - 1);
            }
        }
    }
}

이 경우 기본적으로 함수를 세 번 강조 표시했습니다.일부 컴파일러는 이 최적화를 수행합니다.MSVC++는 재귀함수에 대해 실행되는 인라이닝 수준을 조정하는 설정이 있었던 것으로 기억합니다(최대 20개까지).

하지 않는 컴파일러는 하려고 할 수 .inline coded를 .그러나 대부분의 최신 컴파일러는 이를 인식하고 있습니다.하다

  1. 함수의 인라인화가 전혀 이루어지지 않음
  2. 어느 정도 깊이까지 인라인하여 종료되지 않은 경우 표준 함수 호출 규칙을 사용하여 함수의 개별 인스턴스를 호출합니다.이것에 의해, 많은 일반적인 케이스가 고성능으로 처리되는 한편, 콜의 깊이가 큰 드문 케이스에 대해서는 폴백을 남길 수 있습니다.이는 또한 해당 함수의 코드의 인라인 버전과 개별 버전을 모두 주변에 유지한다는 의미이기도 합니다.

2의 , 가 「2」를 .#pragmas 이 작업을 수행할 최대 깊이를 지정하도록 설정할 수 있습니다.gcc에서는 명령줄에서 이 정보를 전달할 수도 있습니다.--max-inline-insns-recursive(자세한 것은 이쪽).

통상적으로 동작하지 않는 이유에 대해서는, 이미 답을 참조해 주세요.

"각주"로서 템플릿 메타프로그래밍을 사용하여 원하는 효과(적어도 예제로 사용하는 요인)를 얻을 수 있습니다.Wikipedia에서 붙여넣기:

template <int N>
struct Factorial 
{
    enum { value = N * Factorial<N - 1>::value };
};

template <>
struct Factorial<0> 
{
    enum { value = 1 };
};

AFAIK GCC는 가능한 경우 재귀 함수에 대한 테일콜 제거를 수행합니다.그러나 함수는 테일 재귀적이지 않습니다.

컴파일러는 호출 그래프를 생성합니다. 사이클이 자체를 호출하는 것이 감지되면 함수는 특정 깊이(n=1, 10, 100, 컴파일러가 조정된 범위) 후에 더 이상 인라인화되지 않습니다.

일부 재귀 함수는 루프로 변환될 수 있으며, 이는 실질적으로 무한 인라인을 형성합니다.gcc는 가능하지만 다른 컴파일러에 대해서는 잘 모릅니다.

컴파일러는 이러한 것들을 탐지하고 방지하기 위해 호출 그래프를 만듭니다.즉, 함수가 자신을 호출하고, 인라인이 아닌 것을 알 수 있습니다.

단, 주로 inline 키워드와 컴파일러 스위치에 의해 제어됩니다(예를 들어 키워드가 없어도 자동 인라인 스몰 함수를 설정할 수 있습니다).디버깅 컴파일은 인라인화하지 마십시오.콜 스택은 코드로 작성된 콜을 미러링하기 위해 유지되지 않으므로 주의해 주십시오.

"컴파일러는 함수를 인라인화할지 여부를 어떻게 결정합니까?"

컴파일러, 지정된 옵션, 컴파일러 버전 번호, 사용 가능한 메모리 용량 등에 따라 달라집니다.

프로그램의 소스 코드는 여전히 인라인 함수에 대한 규칙을 따라야 합니다.함수가 삽입되는지 여부에 관계없이 삽입될 가능성에 대비해야 합니다(몇 가지 알 수 없는 횟수).

재귀적 매크로가 일반적으로 불법이라는 위키피디아 문장은 정보가 부족한 것처럼 보입니다.C 및 C++는 재귀 호출을 방지하지만 변환 단위는 재귀적으로 보이는 매크로 코드를 포함하므로 불법이 되지 않습니다.어셈블러에서 재귀 매크로는 일반적으로 합법적입니다.

일부 컴파일러(예: Borland C++)는 조건문(예: 대/소문자, 기타)을 포함하는 인라인 코드를 사용하지 않기 때문에 예제의 재귀 함수는 인라인되지 않습니다.

언급URL : https://stackoverflow.com/questions/190232/can-a-recursive-function-be-inline

반응형