Znalazłem ten fragment kodu na GitHub, ale nie do końca go zrozumiałem:
#define lambda(ret_type, _body) ({ ret_type _ _body _; })
Następnie:
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
Co robią podkreślenia wewnątrz #define
i jak zwraca wskaźnik funkcji?
gcc -E
), aby zobaczyć, co on robi?Odpowiedzi:
Za pomocą tego makra
rozwija się do:
W nawiasach klamrowych korzysta z funkcji zagnieżdżonych GCC, aby utworzyć funkcję, która wykonuje żądaną operację. W zakresie wewnętrznym ma nazwę
_
.Następnie, jak zauważył interjay, używane są wyrażenia instrukcji GCC . W efekcie funkcja
_
jest przypisana do wskaźnikamax
.Jeśli takie makro nie jest używane, można je zapisać inaczej i użyć jako:
Trzy metody można porównać w tym przykładzie kodu .
źródło
max(4, -30);
tego zrobić zamiastapply_binary_op(max, 4, -30);
?Nazywa się to wyrażeniem instrukcji i tworzy „lambda” (lub funkcję zagnieżdżoną ) i zwraca do niej wskaźnik. Jest to specyficzne dla GNU C.
Makro rozwija się do:
Na
_
końcu jest jakreturn
.Podkreślenie to tak naprawdę nazwa funkcji, która została utworzona i „zwrócona”. Jest używany, ponieważ jest to rzadko używany identyfikator (nie bez powodu;
_
jest to możliwie najmniej opisowy identyfikator).Powodem użycia wyrażenia jest to,
_
że nie zostanie zdefiniowane po zakończeniu zakresu wyrażenia wyrażenia.Przeglądając makro:
ret_type
jest typem zwracanym „lambda”._
to nazwa funkcji użytej w nim, ponieważ jest to rzadka nazwa identyfikatora._body
składa się z argumentów i treści funkcji. Końcowy_
„zwraca” „lambda”.Ten kod znajduje się w Let's Destroy C (która jest odpowiednią nazwą). Nie powinieneś go używać. Sprawi, że Twój kod będzie działał tylko na kompilatorach obsługujących rozszerzenia GNU C. Zamiast tego po prostu napisz funkcję lub makro.
Jeśli często używasz takich konstrukcji lub chcesz więcej funkcji, sugeruję użycie C ++. Z C ++ możesz zrobić coś podobnego i mieć przenośny kod.
źródło