4.3.3. __pure

순수 함수는 같은 인수로 호출하면 항상 같은 결과를 반환하는 함수입니다.

기본적으로 순수 함수에 대한 모든 특정 호출은 한 번만 평가하면 됩니다. 동일한 함수에 대한 호출 결과는 모두 동일하기 때문에 이후에 수행되는 코드의 함수에 대한 각 호출은 원래 호출의 결과로 대체될 수 있습니다. CSE(공통 하위식 제거)로 알려진 컴파일러 최적화의 인스턴스입니다.

함수가 순수 함수임을 컴파일러에 알리려면 함수를 __pure로 선언합니다.

Table 4.7에서는 __pure 키워드를 사용하는 두 개의 샘플 루틴을 보여 줍니다. 루틴 둘 다 함수 fact를 호출하여 n!n!의 합을 계산합니다. fact 함수는 n!을 계산하는데 입력 인수 n에 따라서만 달라집니다. 따라서 fact는 순수 함수입니다.

첫 번째 루틴은 fact__pure로 선언되지 않는 fact 함수의 원래 구현을 보여 줍니다. 두 번째 구현에서는 컴파일러에 순수 함수임을 알리기 위해 fact 함수가 __pure로 정규화됩니다.

Table 4.7. 순수 함수 및 순수하지 않은 함수에 대한 C 코드 

__pure로 선언되지 않은 순수 함수__pure로 선언된 순수 함수
int fact(int n)
{
    int f = 1;

    while (n > 0)
        f *= n--;
    return f;
} 

int foo(int n)
{
    return fact(n)+fact(n);
}
int fact(int n) __pure
{
    int f = 1;

    while (n > 0)
        f *= n--;
    return f;
}

int foo(int n)
{
    return fact(n)+fact(n);
}

Table 4.8에서는 Table 4.7의 각 샘플 구현에 대해 컴파일러에서 생성된 기계어 코드의 디스어셈블리를 보여 줍니다. 여기서 이 두 가지 구현을 위한 C 코드는 -O2 옵션을 사용하여 컴파일되었습니다.

Table 4.8. 순수 함수 및 순수하지 않은 함수에 대한 디스어셈블리 

__pure로 선언되지 않은 순수 함수__pure로 선언된 순수 함수
fact PROC
    ...
foo PROC
    MOV      r3, r0
    PUSH     {lr}
    BL       fact
    MOV      r2, r0
    MOV      r0, r3
    BL       fact
    ADD      r0, r0, r2
    POP      {pc}
    ENDP
fact PROC
    ...

foo PROC
    PUSH     {lr}
    BL       fact
    LSL      r0,r0,#1
    POP      {pc}
    ENDP

fact__pure로 정규화되지 않는 표 4-8의 함수 foo의 디스어셈블리에서 컴파일러는 함수가 CSE를 위한 것임을 모르기 때문에 fact 함수는 두 번 호출됩니다. 반면에 fact__pure로 정규화되지 않는 표 4-8의 foo 디스어셈블리에서 컴파일러는 fact(n) + fact(n)를 추가할 때 CSE를 수행할 수 있기 때문에 fact는 두 번이 아니라 한 번만 호출됩니다.

순수 함수에는 말 그대로 역효과가 있을 수 없습니다. 예를 들어 전역 상태에 액세스하면 같은 매개변수로 두 번 호출할 때마다 함수는 같은 값을 반환해야 한다는 규칙이 위반되기 때문에 순수 함수는 전역 변수를 사용하거나 포인터를 통해 지시하여 전역 상태를 쓰거나 읽을 수 없습니다. 따라서 프로그램에서 __pure를 사용할 때는 신중해야 합니다. 그러나 함수를 __pure로 선언할 수 없는 경우 컴파일러는 CSE와 같은 강력한 최적화를 수행할 수도 있습니다.

순수 함수에 대한 자세한 내용은 Compiler Reference Guide4-14페이지의 __pure를 참조하십시오.

Copyright © 2002-2007 ARM Limited. All rights reserved.ARM DUI 0205HK
Non-Confidential