2012-01-22 12 views
7

Lo standard C indica che, per una definizione di funzione, se il dichiarante include un elenco di identificatori, i tipi dei parametri devono essere dichiarati in un elenco di dichiarazione successivo. Apparentemente questo fa la differenza.Dichiarazione dei parametri all'esterno del dichiaratore

extern int max(int a, int b) 
{ 
return a > b ? a : b; 
} 

extern int max(a, b) 
int a, b; 
{ 
return a > b ? a : b; 
} 

Qui int a, b; è la lista di dichiarazione per i parametri. La differenza tra queste due definizioni è che il primo modulo agisce come una dichiarazione di prototipo che impone la conversione degli argomenti delle chiamate successive alla funzione, mentre il secondo modulo non lo fa.

Cosa significa questo per il programmatore e influisce sul codice prodotto dal compilatore?

risposta

11

Significa che nel secondo caso, è responsabilità del chiamante assicurarsi che gli argomenti forniti siano del tipo corretto; non verrà fornita alcuna conversione implicita (oltre alle promozioni degli argomenti predefiniti). Dalla sezione 6.5.2.2:

Se l'espressione che indica la funzione chiamata ha un tipo che non include un prototipo , promozioni interi vengono eseguite su ciascun argomento.

...

Se l'espressione che indica la funzione chiamata ha un tipo che include un prototipo, gli argomenti sono implicitamente convertiti, come per l'assegnazione, ai tipi dei parametri corrispondenti .

Quindi chiamando il codice come questo sarà ok:

char x = 3; 
char y = 7; 
max(x, y); // Equivalent to max((int)x, (int)y) 

perché x e y sono promossi a int prima di essere immessi in pila.

Tuttavia, il codice come questo non sarà ok:

double x = 3.0; 
long y = 7; 
max(x, y); // Uh-oh 

x e y sarà posto in pila come double e long, ma max() tenterà di leggere due int s, che si tradurrà in non definito comportamento (in pratica, i bit grezzi saranno reinterpretati).

Questa è una ragione per non utilizzare il secondo modulo; l'unica ragione per cui è nello standard è di fornire la retrocompatibilità con il codice (estremamente) legacy. Se stai utilizzando GCC, puoi applicarlo utilizzando il flag -Wold-style-definition; Spero che altri compilatori offrano qualcosa di equivalente.

Problemi correlati