Typedef e #define sono uguali in c?


Risposte:


122

No.

#defineè un token del preprocessore: il compilatore stesso non lo vedrà mai.
typedefè un token del compilatore: al preprocessore non interessa.

Puoi usare l'uno o l'altro per ottenere lo stesso effetto, ma è meglio usare quello adatto alle tue esigenze

#define MY_TYPE int
typedef int My_Type;

Quando le cose diventano "pelose", l'uso dello strumento appropriato lo fa bene

#define FX_TYPE void (*)(int)
typedef void (*stdfx)(int);

void fx_typ(stdfx fx); /* ok */
void fx_def(FX_TYPE fx); /* error */

3
Dopo il typedef stdfx, gli oggetti validi di quel tipo sono puntatori a funzioni che ricevono un int e non restituiscono un valore.
pmg

1
Perché #define fallisce nel caso del puntatore a funzione come argomento?
Allahjane

2
@Allahjane: l'espansione diventa void fx_def(void (*)(int) fx);; la dichiarazione corretta è void fx_def(void (*fx)(int));.
pmg

5
Puntatori a funzione sono fattibile con le macro, solo se si è pronti a rinunciare sintassi: #define FX_TYPE(f) void (*f)(int). Dovresti quindi dichiarare la tua funzione come:void fx_def(FX_TYPE(fx));
plafer

229

typedefobbedisce alle regole di scoping proprio come le variabili, mentre definerimane valido fino alla fine dell'unità di compilazione (o fino a una corrispondenza undef).

Inoltre, si possono fare alcune cose typedefche non possono essere fatte define.
Per esempio:

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

23

No, non sono la stessa cosa. Per esempio:

#define INTPTR int*
...
INTPTR a, b;

Dopo la preelaborazione, quella riga si espande in

int* a, b;

Si spera che tu veda il problema; aavrà solo il tipo int *; bsarà dichiarato normale int(perché *è associato al dichiaratore, non all'identificatore di tipo).

Confrontalo con

typedef int *INTPTR;
...
INTPTR a, b;

In questo caso, entrambi ae bavranno tipo int *.

Esistono intere classi di typedef che non possono essere emulati con una macro del preprocessore, come i puntatori a funzioni o array:

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

Prova a farlo con una macro del preprocessore.


13

#define definisce le macro.
typedef definisce i tipi.

Detto questo, ecco alcune differenze:

Con #define puoi definire costanti che possono essere utilizzate in fase di compilazione. Le costanti possono essere utilizzate con #ifdef per verificare come viene compilato il codice e specializzare determinati codici in base ai parametri di compilazione.
Puoi anche usare #define per dichiarare funzioni macro trova e sostituisci in miniatura .

typedef può essere usato per dare alias ai tipi (cosa che potresti probabilmente fare anche con #define ), ma è più sicuro a causa della natura trova e sostituisci delle costanti #define .
Oltre a ciò, puoi utilizzare la dichiarazione in avanti con typedef che ti consente di dichiarare un tipo che verrà utilizzato, ma non è ancora collegato al file in cui stai scrivendo.


cosa intendi per trovare e sostituire la natura di #define? , Grazie
Mohamed El Shenawy

1
Significa che prima della compilazione, il preprocessore troverà tutte le macro e le sostituirà con la loro sintassi originale
Prince Vijay Pratap

"typedef può essere usato per dare alias ai tipi" Questo mi ha spiegato lo scopo, grazie.
Dave Voyles

8

Le macro del preprocessore (" #define's") sono uno strumento di sostituzione lessicale alla "ricerca e sostituzione". Sono completamente agnostici del linguaggio di programmazione e non capiscono cosa stai cercando di fare. Puoi pensarli come una glorificata meccanica copia / incolla - a volte è utile, ma dovresti usarla con cura.

I typedef sono una funzionalità del linguaggio C che ti consente di creare alias per i tipi. Ciò è estremamente utile per rendere leggibili e gestibili tipi composti complicati (come strutture e puntatori a funzione) (in C ++ ci sono anche situazioni in cui è necessario digitare un tipo).

Per (3): dovresti sempre preferire le funzionalità del linguaggio rispetto alle macro del preprocessore quando è possibile! Quindi usa sempre typedef per i tipi e valori costanti per le costanti. In questo modo, il compilatore può effettivamente interagire con te in modo significativo. Ricorda che il compilatore è tuo amico, quindi dovresti dirlo il più possibile. Le macro del preprocessore fanno l'esatto opposto nascondendo la tua semantica al compilatore.


Puoi dire un esempio in C ++ in cui devi typedef un tipo? Sono solo curioso di questo.
jyz

@jyzuz: C'è qualcosa se vuoi che una funzione membro restituisca un array di puntatori a funzione, o qualcosa del genere - se provi a precisare il tipo, GCC in realtà dice "devi usare un typedef".
Kerrek SB

4

Sono molto diversi, sebbene vengano spesso utilizzati per implementare tipi di dati personalizzati (che è ciò che presumo sia questa domanda).

Come accennato in pmg, #defineviene gestito dal pre-processore (come un'operazione taglia e incolla) prima che il compilatore veda il codice e typedefvenga interpretato dal compilatore.

Una delle principali differenze (almeno quando si tratta di definire i tipi di dati) è che typedefconsente un controllo del tipo più specifico. Per esempio,

#define defType int
typedef int tdType

defType x;
tdType y;

Qui, il compilatore vede la variabile x come un int, ma la variabile y come un tipo di dati chiamato "tdType" che sembra avere le stesse dimensioni di un int. Se hai scritto una funzione che ha un parametro di tipo defType, il chiamante potrebbe passare un normale int e il compilatore non conoscerebbe la differenza. Se invece la funzione prendesse un parametro di tipo tdType, il compilatore garantirebbe che una variabile del tipo corretto fosse utilizzata durante le chiamate di funzione.

Inoltre, alcuni debugger hanno la capacità di gestire typedefi messaggi di posta elettronica , il che può essere molto più utile che avere tutti i tipi personalizzati elencati come tipi primitivi sottostanti (come sarebbe se #definefosse usato invece).


2

No.
typedef è una parola chiave C che crea un alias per un tipo.
#define è un'istruzione pre-processore, che crea un evento di sostituzione del testo prima della compilazione. Quando il compilatore arriva al codice, la parola originale "#defined" non è più presente. #define viene utilizzato principalmente per macro e costanti globali.


2
L'uso del termine "puntatore" potrebbe creare confusione qui.

Concordato. Ecco perché sono tornato indietro e ho aggiunto un collegamento a typdef su MSDN, nel caso in cui qualcuno in futuro utilizzerà questa domanda per trovare cos'è typedef. Ma forse dovrei cambiare quella parola ...
Travelling Tech Guy

2

AFAIK, No.

typedefti aiuta a impostare un "alias" per un tipo di dati esistente. Per es. typedef char chr;

#defineè una direttiva del preprocessore utilizzata per definire macro o sostituzioni di pattern generali. Per es. #define MAX 100, sostituisce tutte le occorrenze di MAXcon 100


0

Come accennato in precedenza, esiste una differenza fondamentale tra #definee typedef. Il modo giusto per pensarci è vedere un typedef come un tipo "incapsulato" completo. Significa che non puoi aggiungerlo dopo averlo dichiarato.

Puoi estendere il nome di un tipo di macro con altri specificatori di tipo, ma non con un nome di tipo predefinito:

#define fruit int
unsigned fruit i;   // works fine

typedef int fruit;
unsigned fruit i;   // illegal

Inoltre, un nome typedef fornisce il tipo per ogni declatore in una dichiarazione.

#define fruit int *
fruit apple, banana;

Dopo l'espansione della macro, la seconda riga diventa:

int *apple, banana;

Apple è un puntatore a un int, mentre banana è un int. In confronto. un typedef come questo:

typedef char *fruit;
fruit apple, banana;

dichiara che sia la mela che la banana sono la stessa cosa. Il nome sulla parte anteriore è diverso, ma sono entrambi puntatori a un carattere.


-1

Come tutti hanno detto sopra, non sono la stessa cosa. La maggior parte delle risposte indica typedefdi essere più vantaggiosa di #define. Ma lasciatemi mettere un punto in più #define:
quando il vostro codice è estremamente grande, sparpagliato in molti file, è meglio usarlo #define; aiuta nella leggibilità: puoi semplicemente preelaborare tutto il codice per vedere l'effettiva definizione del tipo di una variabile al posto della sua dichiarazione stessa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.