2015-04-27 5 views
13

Mentre si passa attraverso un codice sorgente che mescola pesantemente C e C++, mi sono imbattuto in quanto segue (leggermente modificato per proteggere il lavoro dell'azienda, il significato rimane il stessa):Implicazioni di typedef void FOO vs. #define FOO void nelle firme delle funzioni

/* 
* Typedefs of void are synonymous with the void keyword in C, 
* but not in C++. In order to support the use of MY_VOID 
* in place of the void keyword to specify that a function takes no 
* arguments, it must be a macro rather than a typedef. 
*/ 
#define MY_VOID void 

Qual è la differenza tra typedef void MY_VOID e #define MY_VOID void in questo specifico contesto?


io non credo che questo è un duplicato di this question perché chiede specificamente per le implicazioni per quanto riguarda la funzione di firme, piuttosto che un molto più generale "che cosa è la differenza".

+0

È ben spiegato qui http://programmers.stackexchange.com/questions/130679/typedefs-and-defines – Morb

+2

@Morb: ciò spiega perché di solito preferisci un 'typedef' ma, per quanto posso vedere, non spiega perché non puoi in questo caso particolare. –

+2

Non vedo come questa domanda né la risposta accettata stiano dicendo qualcosa di diverso rispetto alla domanda precedente ... Quindi l'ho contrassegnato come un duplicato. – Nemo

risposta

8

Un semplice programma di test in C++ dimostra la differenza:

typedef void VOID; 

void f(VOID) {} 

int main() 
{ 
    f(); 
} 

On compilazione (come C++), it gives these error:

prog.cpp:5:8: error: '<anonymous>' has incomplete type 
void f(VOID) {} 
     ^
prog.cpp:5:12: error: invalid use of 'VOID {aka void}' 
void f(VOID) {} 
      ^
prog.cpp: In function 'int main()': 
prog.cpp:9:7: error: too few arguments to function 'void f(<type error>)' 
    f(); 
    ^
prog.cpp:5:6: note: declared here 
void f(VOID) {} 
    ^

che spiega cosa significa il commento nel codice. In particolare, sembra che il typedef VOID tenta di essere un tipo diverso da void, quando viene utilizzato come tipo di parametro.

+0

Non proprio, come una funzione con VOID dato che il tipo di ritorno è trattato proprio come una normale funzione void in C++ – Mints97

+2

@ Mints97 "* quando è usato come tipo di parametro *". – Nawaz

+2

sì, esattamente. Mi chiedo dove siano gli standard nelle differenze. – Mints97

-1

È possibile utilizzare entrambi, stanno facendo la stessa cosa quindi l'unica differenza è che usando #define dichiarerai il tuo nuovo tipo come una macro.

+1

grazie per aver provato a rispondere, tuttavia risulta non corretto. :) – OMGtechy

3

Il commento si riferisce al codice come questo:

typedef void my_void_t; 
my_void_t foo(my_void_t); // Illegal. 

Con la #define è legale.

5

Il commento spiega la differenza. Dato un alias per void:

typedef void MY_VOID; 

Se si tenta di utilizzare questo invece di void per indicare che una funzione non accetta parametri:

int f(MY_VOID); 

C permetterà questo, ma C++ non lo faranno.

Quindi, se vuoi veramente rendere la vita difficile per te scrivendo il codice che (a) è valido in entrambe le lingue e (b) usa un alias per questo particolare uso di void, quell'alias dovrà essere una macro .

1

Un estratto dagli standard linguistici può migliorare tutto!

C99, 6.7.5.3/10:

Il caso particolare di un parametro senza nome di tipo void come l'unico elemento nella lista speci ca fi che la funzione non ha parametri.

C++, 8.3.5/2:

Se la clausola-dichiarazione-parametro è vuota, la funzione non accetta argomenti. L'elenco dei parametri (void) è equivalente alla lista dei parametri vuota.

La differenza è evidente. C ha il void in questione come parametro senza nome di tipo void e C++ ha l'identificatore void. Il primo può essere typedef -ed, quest'ultimo non può.

Potrebbe essere interessante riflettere sui motivi di ciò. In realtà, il seguente è legale in C++, ma illegale in C:

void fn(int){ 
} 

come C++ ha il concetto di parametri (anonimo) Senza nome in definizioni di funzioni, non mentre C fa ... Quasi.

In realtà, un parametro senza nome può essere presente in una definizione di funzione C: una di tipo void.

Che sicuramente non ha molto senso poiché non può esserci alcun parametro con questo tipo.

Oltre a non avere molto senso, questa definizione di void nell'elenco parametri potrebbe rovinare i parametri senza nome di C++, in quanto non sarebbe diverso da loro. La definizione potrebbe essere stata modificata per renderlo un caso speciale molto-molto-vero di un parametro senza nome che non ha parametri corrispondenti corrispondenti e non può essere utilizzato con altri parametri con nome o senza nome e non è in realtà un parametro e ...

Ma immagino che invece di cercare di esprimere qualcosa di così folle, il comitato del C++ ha semplicemente deciso di abbandonare completamente la sezione "unnamed-void-type-parameter" e andare con la "lista dei parametri speciali". Dico buona liberazione.

E lo standard C? Probabilmente mantiene il suo strano 6.7.5.3/10 per motivi di compatibilità con le versioni precedenti ...