Uczę się, jak dynamicznie ładować biblioteki DLL, ale nie rozumiem tej linii
typedef void (*FunctionFunc)();
Mam parę pytań. Gdyby ktoś był w stanie na nie odpowiedzieć, byłbym wdzięczny.
- Dlaczego jest
typedef
używany? - Składnia wygląda dziwnie; po
void
czy nie powinna być nazwa funkcji czy coś? Wygląda jak funkcja anonimowa. - Czy wskaźnik funkcji został utworzony w celu przechowywania adresu pamięci funkcji?
W tej chwili jestem zdezorientowany; czy możesz mi wyjaśnić?
using FunctionFunc = void (*)();
zamiast tego można użyć c ++ 11 . Jest nieco bardziej jasne, że właśnieusing FunctionFunc = void(void);
*
jest nieco bardziej wyraźna.Odpowiedzi:
typedef
to konstrukcja języka, która wiąże nazwę z typem.Używasz go na przykład w taki sam sposób, jak oryginalnego typu
używając ich jak
Jak widać, możesz po prostu zastąpić nazwę pisma maszynowego jej definicją podaną powyżej.
Trudność polega na wskaźniku składni funkcji i czytelności w C i C ++, a także
typedef
może poprawić czytelność takich deklaracji. Jednak składnia jest odpowiednia, ponieważ funkcje - w przeciwieństwie do innych prostszych typów - mogą mieć zwracaną wartość i parametry, a zatem czasem długą i złożoną deklarację wskaźnika do funkcji.Czytelność może być naprawdę trudna w przypadku wskaźników do tablic funkcji i niektórych innych, nawet bardziej pośrednich smaków.
Aby odpowiedzieć na trzy pytania
Dlaczego używany jest typedef? Aby ułatwić odczyt kodu - szczególnie w przypadku wskaźników do funkcji lub nazw struktur.
Składnia wygląda dziwnie (we wskaźniku do deklaracji funkcji) Ta składnia nie jest oczywista do odczytania, przynajmniej na początku. Użycie
typedef
deklaracji zamiast tego ułatwia odczytCzy wskaźnik funkcji został utworzony w celu przechowywania adresu pamięci funkcji? Tak, wskaźnik funkcji przechowuje adres funkcji. Nie ma to nic wspólnego z
typedef
konstrukcją, która jedynie ułatwia pisanie / czytanie programu; kompilator po prostu rozszerza definicję typedef przed skompilowaniem rzeczywistego kodu.Przykład:
źródło
typedef type alias
, ale z wskazówki funkcjonują tylko wydaje się być 2 argumentytypedef type
. Czy domyślny alias ma nazwę podaną w argumencie type?square
i&square
(i rzeczywiście*square
i**square
) odnoszą się do tego samego wskaźnika funkcji.typedef int newname
tworzysznewname
alias dlaint
. Za pomocątypedef int (*func)(int)
przekształcaszfunc
się w aliasint (*)(int)
- wskaźnik do funkcji, który przyjmujeint
argument i zwracaint
wartość.int (*func)(int)
rozumiem, że func jest aliasem, tylko trochę pomieszanym, ponieważ alias jest splątany z typem. Przechodząctypedef int INT
jako przykład, byłbym bardziej swobodny, gdyby wskaźnik funkcji typedef miał formętypedef int(*function)(int) FUNC_1
. W ten sposób widzę typ i alias w dwóch osobnych tokenach zamiast w siatce.typedef
jest używany do typów aliasów; w tym przypadku jesteś aliasFunctionFunc
dovoid(*)()
.Rzeczywiście składnia wygląda dziwnie, spójrz na to:
Nie, to po prostu mówi kompilatorowi, że
FunctionFunc
typ będzie wskaźnikiem funkcji, nie definiuje go, jak poniżej:źródło
typedef
czy nie zadeklarować nowy typ. możesz mieć wieletypedef
zdefiniowanych nazw tego samego typu i nie są one różne (np. wrt. przeciążenie funkcji). istnieją pewne okoliczności, w których pod względem sposobu używania nazwytypedef
-definowana nazwa nie jest dokładnie równoważna z definicją, ale wielokrotnetypedef
zdefiniowane dla niej nazwy są równoważne.Bez
typedef
słowa, w C ++ deklaracja deklarowałaby zmiennąFunctionFunc
typu wskaźnik do funkcji bez argumentów, zwracającvoid
.Z
typedef
to zamiast definiujeFunctionFunc
jako nazwa dla tego typu.źródło
Jeśli możesz używać C ++ 11, możesz chcieć użyć
std::function
iusing
słowa kluczowego.źródło
using
słowa kluczowego C ++ 11 byłobytypedef std::function<void(int, std::string)> FunctionFunc;
na wypadek, gdyby ktoś chciał innego opakowania funkcji bez C ++ 11źródło
typedef (*double) p
operacji podstawowej użyty zostanie typedef (tj. Czy opcja „&” jest opcjonalna?typedef double* p
aby zdefiniować wskaźnik do podwójnego. Jeśli chcesz wypełnićp
wskaźnik pierwotną zmienną, musisz użyć „&”. Uwaga dodatkowa: my * <nazwa wskaźnika>, aby wyrejestrować wskaźnik.*
Jest używana w funkcji wskaźnika do nieprawidłowego wskaźnika (nazwy funkcji) i przejdź do bloku pamięci, gdzie znajdują się instrukcje funkcyjne.Ogólny przypadek składni można znaleźć w załączniku A normy ANSI C. .
Stamtąd w formularzu Backus-Naur można zobaczyć, że
typedef
ma on typstorage-class-specifier
.W typie
declaration-specifiers
widać, że można mieszać wiele typów specyfikatorów, których kolejność nie ma znaczenia.Na przykład poprawne jest powiedzenie
zdefiniować typ
a
jako alias dlalong long
. Tak więc, aby zrozumieć typedef wyczerpującego użycia, musisz skonsultować się z pewną formą backus-naur, która definiuje składnię (istnieje wiele poprawnych gramatyk dla ANSI C, nie tylko ISO).Kiedy używasz typedef do zdefiniowania aliasu dla typu funkcji, musisz umieścić alias w tym samym miejscu, w którym umieścisz identyfikator funkcji. W twoim przypadku definiujesz typ
FunctionFunc
jako alias wskaźnika, który działa, którego sprawdzanie typu jest wyłączone podczas połączenia i nic nie zwraca.źródło