Odpowiedzi:
Nie.
#define
jest tokenem preprocesora: sam kompilator nigdy go nie zobaczy.
typedef
jest tokenem kompilatora: preprocesor nie dba o to.
Możesz użyć jednego lub drugiego, aby osiągnąć ten sam efekt, ale lepiej użyć odpowiedniego dla swoich potrzeb
#define MY_TYPE int
typedef int My_Type;
Kiedy robi się „owłosiona”, użycie odpowiedniego narzędzia naprawia to
#define FX_TYPE void (*)(int)
typedef void (*stdfx)(int);
void fx_typ(stdfx fx); /* ok */
void fx_def(FX_TYPE fx); /* error */
void fx_def(void (*)(int) fx);
; prawidłowa deklaracja to void fx_def(void (*fx)(int));
.
#define FX_TYPE(f) void (*f)(int)
. Następnie zadeklarowałbyś swoją funkcję jako:void fx_def(FX_TYPE(fx));
typedef
przestrzega reguł określania zakresu tak samo jak zmienne, ale define
pozostaje ważna do końca jednostki kompilacji (lub do dopasowania undef
).
Ponadto można zrobić z typedef
tym pewne rzeczy , których nie można zrobić define
.
Na przykład:
typedef int* int_p1;
int_p1 a, b, c; // a, b, c are all int pointers
#define int_p2 int*
int_p2 a, b, c; // only the first is a pointer, because int_p2
// is replaced with int*, producing: int* a, b, c
// which should be read as: int *a, b, c
typedef int a10[10];
a10 a, b, c; // create three 10-int arrays
typedef int (*func_p) (int);
func_p fp; // func_p is a pointer to a function that
// takes an int and returns an int
Nie, to nie to samo. Na przykład:
#define INTPTR int*
...
INTPTR a, b;
Po wstępnym przetworzeniu ta linia rozwija się do
int* a, b;
Miejmy nadzieję, że widzisz problem; tylko a
będzie miał typ int *
; b
zostanie zadeklarowany jako zwykły int
(ponieważ *
jest skojarzony z deklaratorem, a nie specyfikatorem typu).
Porównaj to z
typedef int *INTPTR;
...
INTPTR a, b;
W takim przypadku oba a
i b
będą miały typ int *
.
Istnieją całe klasy typedef, których nie można emulować za pomocą makra preprocesora, na przykład wskaźniki do funkcji lub tablic:
typedef int (*CALLBACK)(void);
typedef int *(*(*OBNOXIOUSFUNC)(void))[20];
...
CALLBACK aCallbackFunc; // aCallbackFunc is a pointer to a function
// returning int
OBNOXIOUSFUNC anObnoxiousFunc; // anObnoxiousFunc is a pointer to a function
// returning a pointer to a 20-element array
// of pointers to int
Spróbuj to zrobić za pomocą makra preprocesora.
#define definiuje makra.
typedef definiuje typy.
Mówiąc to, oto kilka różnic:
Za pomocą #define możesz zdefiniować stałe, które mogą być używane w czasie kompilacji. Stałe mogą być używane z #ifdef, aby sprawdzić, jak kod jest kompilowany, i specjalizować określony kod zgodnie z parametrami kompilacji.
Możesz także użyć #define, aby zadeklarować miniaturowe funkcje makra znajdź i zamień .
typedef może służyć do nadawania aliasów typom (co prawdopodobnie można by zrobić również za pomocą #define ), ale jest to bezpieczniejsze ze względu na naturę #define typu znajdź i zamień .
Poza tym możesz użyć deklaracji forward z typedef, która pozwala zadeklarować typ, który będzie używany, ale nie jest jeszcze powiązany z plikiem, w którym piszesz.
Makra preprocesora („ #define
s”) są leksykalnym narzędziem zastępującym a la „wyszukaj i zamień”. Są całkowicie agnostykami języka programowania i nie rozumieją, co próbujesz zrobić. Możesz myśleć o nich jako o chwalebnym mechanizmie kopiowania / wklejania - czasami jest to przydatne, ale powinieneś używać go ostrożnie.
Typedef to funkcja języka C, która umożliwia tworzenie aliasów dla typów. Jest to niezwykle przydatne, aby skomplikowane typy złożone (takie jak struktury i wskaźniki funkcji) były czytelne i obsługiwane (w C ++ są nawet sytuacje, w których trzeba wpisać typ).
Dla (3): Zawsze powinieneś preferować funkcje językowe od makr preprocesora, kiedy jest to możliwe! Dlatego zawsze używaj typedef dla typów i stałych wartości dla stałych. W ten sposób kompilator może faktycznie współdziałać z Tobą. Pamiętaj, że kompilator jest twoim przyjacielem, więc powinieneś mu powiedzieć jak najwięcej. Makra preprocesora działają dokładnie odwrotnie, ukrywając semantykę przed kompilatorem.
Są bardzo różne, chociaż często są używane do implementacji niestandardowych typów danych (i zakładam, że o to chodzi w tym pytaniu).
Jak wspomniano, pmg #define
jest obsługiwany przez preprocesor (podobnie jak operacja wycinania i wklejania), zanim kompilator zobaczy kod, itypedef
jest interpretowany przez kompilator.
Jedną z głównych różnic (przynajmniej jeśli chodzi o definiowanie typów danych) jest to, że typedef
umożliwia bardziej szczegółowe sprawdzanie typów. Na przykład,
#define defType int
typedef int tdType
defType x;
tdType y;
Tutaj kompilator widzi zmienną x jako int, ale zmienną y jako typ danych o nazwie „tdType”, który ma taki sam rozmiar jak int. Jeśli napisałeś funkcję, która przyjęłaby parametr typu defType, wywołujący mógłby przekazać normalną wartość int, a kompilator nie znałby różnicy. Gdyby zamiast tego funkcja przyjęła parametr typu tdType, kompilator zapewni, że podczas wywołań funkcji zostanie użyta zmienna odpowiedniego typu.
Ponadto niektóre debugery mają możliwość obsługi typedef
s, co może być znacznie bardziej przydatne niż umieszczanie wszystkich typów niestandardowych na liście jako ich podstawowe typy pierwotne (tak jakby #define
był używany zamiast tego).
Nie.
Typedef to słowo kluczowe C, które tworzy alias dla typu.
#define to instrukcja preprocesora, która tworzy zdarzenie zamiany tekstu przed kompilacją. Gdy kompilator dotrze do kodu, oryginalne słowo „#defined” już nie istnieje. #define jest używany głównie w przypadku makr i stałych globalnych.
AFAIK, No.
typedef
pomaga ustawić „alias” do istniejącego typu danych. Np. typedef char chr
;
#define
jest dyrektywą preprocesora używaną do definiowania makr lub ogólnych podstawień wzorców. Np. #define MAX 100
, zastępuje wszystkie wystąpienia MAX
100
Jak wspomniano powyżej, istnieje kluczowa różnica między #define
i typedef. Właściwy sposób, aby o tym pomyśleć, to zobaczyć typedef jako kompletny typ „hermetyzowany”. Oznacza to, że po zadeklarowaniu nie możesz do niego nic dodawać.
Możesz rozszerzyć nazwę typu makra o inne specyfikatory typu, ale nie o nazwę typu zdefiniowaną przez typ:
#define fruit int
unsigned fruit i; // works fine
typedef int fruit;
unsigned fruit i; // illegal
Ponadto nazwa typedef'd zapewnia typ dla każdego deklaratora w deklaracji.
#define fruit int *
fruit apple, banana;
Po rozwinięciu makra druga linia staje się:
int *apple, banana;
Apple jest wskaźnikiem do int, a banan to int. W porównaniu. taki typ:
typedef char *fruit;
fruit apple, banana;
deklaruje, że jabłko i banan są takie same. Nazwa na przodzie jest inna, ale oba są wskazówkami do znaku.
Jak wszyscy powiedzieli powyżej, nie są tacy sami. Większość odpowiedzi wskazuje, typedef
że są one bardziej korzystne niż #define
. Ale pozwólcie, że dodam plus #define
:
kiedy twój kod jest bardzo duży, rozproszony w wielu plikach, lepiej go użyć #define
; pomaga w czytelności - możesz po prostu wstępnie przetworzyć cały kod, aby zobaczyć rzeczywistą definicję typu zmiennej w miejscu jej deklaracji.
stdfx
prawidłowe obiekty tego typu są wskaźnikami do funkcji, które otrzymują int i nie zwracają wartości.