람다 매크로는 어떻게 람다를 생성합니까?


20

GitHub 에서이 코드를 찾았지만 이해하지 못했습니다.

#define lambda(ret_type, _body) ({ ret_type _ _body _; })

그때:

int (*max)(int, int) = lambda(int,
                             (int x, int y) {
                                 return x > y ? x : y;
                             });

int max_value = max(1, 2);
// max_value is 2

내부에서 밑줄은 무엇 #define이며 어떻게 함수 포인터를 반환합니까?


7
매크로를 확장하여 매크로의 기능 gcc -E을 확인하려고하십니까 (예 :)?
쓸모없는

5
확장 godbolt.org/z/C5TLWj를보십시오 . 결과는 이해하기 쉽지 않습니다
Eugene Sh.

2
이 코드를 얻은 곳의 주석을 기반으로 알고 있다고 가정하지만 중첩 된 함수의 GCC 확장에 의존합니다.
토마스 Jager

4
@EugeneSh. GCC의 중첩 함수를 사용하여 함수 포인터를 초기화하고 있습니다. 원래 코드는 여기에서 입니다. 이 프로젝트는 오늘 Hacker News에 공유되었습니다.
토마스 예거

4
@EugeneSh. 중첩 된 함수와 표현식의 복합 명령문 인 두 가지 GCC 확장의 조합입니다 . 중첩 된 함수는 복합 명령문 안에 나타납니다.
인터 제이

답변:


10

이 매크로를 사용하면

int (*max)(int, int) = lambda(int,
                             (int x, int y) {
                                 return x > y ? x : y;
                             });

로 확장 :

int (*max)(int, int) = ({
    int _ (int x, int y) { return x > y ? x : y; }
    _;
});

중괄호에서는 GCC의 중첩 함수 를 사용하여 원하는 작업을 수행하는 함수를 만듭니다. 내부 범위 내에서 이름은 _입니다.

그런 다음 interjay가 언급 한대로 GCC의 명령문 표현식 이 사용됩니다. 효과적으로 함수 _가 포인터에 할당됩니다 max.

이러한 매크로를 사용하지 않으면 다르게 작성하여 다음과 같이 사용할 수 있습니다.

int val1 = 4;
int val2 = -30;

int perform_operation(int (*op)(int, int)) {
    int new_val = op(val1, val2);
    val1 = val2;
    val2 = new_val;
    return new_val;
}

int enclosing_function (void) {
    // Create max "lambda"
    int (*max)(int, int);
    {
        // Curly braces limit the scope of _
        int _ (int x, int y) { return x > y ? x : y; }
        max = _;
    }

    return perform_operation(max);
}

이 코드 예제 에서는 세 가지 방법을 비교할 수 있습니다 .


매크로는 gcc에서 컴파일되지 않으므로 아무 것도하지 않습니다
P__J__


@ P__J__ 내 답변 끝에 예제를 추가 하여이 매크로가 사용되고 있음을 보여줍니다.
토마스 예거

max(4, -30);대신에 할 수 apply_binary_op(max, 4, -30);없습니까?
SS Anne

1
"표현식의 문장"을 "표현식"이라고합니다. 예를 들어 어떤 것에 할당 될 수있는 가치가있는 진술.
피터 코데

7

이를 명령문 표현식 이라고하며 "lambda"(또는 중첩 함수 )를 작성하고 이에 대한 포인터를 리턴합니다. GNU C 전용입니다.

매크로는 다음과 같이 확장됩니다.

int (*max)(int, int) = ({ int _ (int x, int y) { return x > y ? x : y; } _; })

_끝은 같다 return.

밑줄은 실제로 만들어지고 "반환 된"함수의 이름입니다. 일반적으로 사용되지 않는 식별자이기 때문에 사용됩니다 (합리적인 이유로 _가능한 가장 설명적인 식별자 일 수 있음).

명령문 표현식이 사용 된 이유는 명령문 표현식 _의 범위가 종료 된 후에는 정의되지 않습니다.

따라서 매크로를 살펴보십시오.

#define lambda(ret_type, _body) ({ ret_type _ _body _; })

ret_type"lambda"의 리턴 유형입니다. _드문 식별자 이름이므로 내부에서 사용되는 함수의 이름입니다. _body함수의 인수와 본문으로 구성됩니다. 후행 _은 "람다"를 "돌아온다".

이 코드는 Let 's Destroy C (적절한 이름)에 있습니다. 당신은 그것을 사용해서는 안됩니다. GNU C 확장을 지원하는 컴파일러에서만 코드가 작동합니다. 대신 함수 나 매크로를 작성하십시오.

이와 같은 구문을 많이 사용하거나 더 많은 기능을 원한다면 C ++을 사용하는 것이 좋습니다. C와 함께 ++이 비슷한 작업을 수행 할 수 있습니다 휴대용 코드가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.