Domanda

Installazione

Ho un paio di domande circa l'argomento di default promozioni quando si chiama una funzione in C.Ecco la sezione 6.5.2.2 la Funzione "chiama" i Paragrafi 6, 7 e 8 del Standard C99 (pdf) (il corsivo è mio e rotto in liste per facilità di lettura):

Paragrafo 6

  1. Se l'espressione che denota la funzione chiamata è un tipo che non include un prototipo, l'intero promozioni vengono eseguite su ogni argomento, e gli argomenti che sono di tipo float sono promosso double.Questi sono chiamati i argomento di default promozioni.
  2. Se il numero di argomenti non è uguale al numero di parametri, il comportamento è indefinito.
  3. Se la funzione è definita con un tipo che include un prototipo, e il prototipo si conclude con i puntini di sospensione (, ...) o i tipi di argomenti dopo la promozione non è compatibile con i tipi dei parametri, il comportamento è indefinito.
  4. Se la funzione è definita con un tipo che non include un prototipo, e i tipi di argomenti dopo la promozione non sono compatibili con quelli dei parametri dopo la promozione, il comportamento è indefinito, fatta eccezione per i seguenti casi:
    • quello promosso tipo è un tipo integer, l'altro promosso tipo è il corrispondente tipo unsigned integer, e il valore è rappresentabile in entrambi i tipi;
    • entrambi i tipi sono dei puntatori a qualificato o non qualificato versioni di un tipo di carattere o void.

Paragrafo 7

  1. Se l'espressione che denota la funzione chiamata è un tipo che include un prototipo, gli argomenti vengono convertiti in modo implicito, come se per assegnazione, per i tipi dei parametri corrispondenti, tenendo il tipo di ogni parametro deve essere qualificati versione del tipo dichiarato.
  2. I puntini di sospensione notazione in un prototipo di funzione dichiaratore cause tipo di argomento di conversione per interrompere dopo l'ultimo parametro dichiarato. L'argomento di default promozioni vengono eseguite finali argomenti.

Paragrafo 8

  1. Non le altre conversioni vengono eseguite in modo implicito;in particolare, il numero e i tipi di argomenti non vengono confrontati con quelli dei parametri nella definizione di una funzione che non includere un prototipo di funzione dichiaratore.

Quello che so

  • Il argomento di default promozioni sono char e short per int/unsigned int e float per double
  • Gli argomenti facoltativi per variadic funzioni (come printf) sono soggetti all'argomento di default promozioni

Per la cronaca, la mia comprensione di un prototipo di funzione è questo:

void func(int a, char b, float c);  // Function prototype
void func(int a, char b, float c) { /* ... */ }  // Function definition

Domanda

Sto avendo un momento davvero difficile groking tutto questo.Qui ci sono alcune domande che ho sono:

  • Fare prototipo e non di prototipi di funzioni di comportamento si discosta così tanto, come per quanto riguarda default promozioni e le conversioni implicite?
  • Quando argomento di default promozioni verificarsi?È sempre?O è solo in casi particolari (come con variadic funzioni)?Dipende da se una funzione è il seguente prototipo?
È stato utile?

Soluzione

Con voto positivo AProgrammer risposta—questi sono i veri beni.

Per quelli di voi che si stanno chiedendo perché le cose stanno in questo modo:nei secoli bui, prima del 1988, non vi era alcuna cosa come un prototipo di funzione nel classico "K&R" C, e l'argomento di default promozioni furono istituiti, perché (a) non c'erano, essenzialmente, "libero", in quanto i costi di non più di mettere un byte in un registro che mettere una parola in un registro, e (b) per ridurre la possibilità di errori nel passaggio dei parametri.Che il secondo motivo è mai abbastanza, che era il motivo per l'introduzione di prototipi di funzione in ANSI C è stato il cambiamento più importante che mai in linguaggio C.

Come quando di default promozioni di calcio in: argomento di default promozioni vengono utilizzati esattamente quando il tipo dell'argomento è sconosciuto, che dire, se non c'è un prototipo o quando l'argomento è variadic.

Altri suggerimenti

  • (non variadic) parametri alle funzioni con un prototipo vengono convertiti nel tipo corrispondente, che può essere char, short, galleggiante.

  • I parametri alle funzioni senza parametri prototipare e variadic sono soggetti a promozioni argomento di default.

Se si definisce una funzione con un prototipo e utilizzarlo senza il prototipo o viceversa ed ha parametri di tipo char, brevi o galleggiante, probabilmente hanno un problema in fase di esecuzione. Avrete lo stesso tipo di problemi con le funzioni variadic se il tipo promosso non corrisponde quello che viene utilizzato quando si legge la lista degli argomenti.

Esempio 1:. Problema quando si definisce una funzione con un prototipo e utilizzarlo senza

definition.c

void f(char c)
{
   printf("%c", c);
}

use.c

void f();

int main()
{
   f('x');
}

può fallire perché int sarà passata e la funzione si aspetta un char.

Esempio 2:. Problema quando si definisce una funzione senza un prototipo e utilizzarlo con uno

definition.c

void f(c)
   char c;
{
   printf("%c", c);
}

(Questa è una specie di definizione è molto vecchio stile)

use.c

void f(char c);

int main()
{
   f('x');
}

può fallire perché si prevede un int, ma sarà passato un char.

Nota: potrai notare che tutte le funzioni della libreria standard hanno tipi derivanti dalle promozioni di default. Così essi non hanno causato problemi durante il passaggio in cui sono stati aggiunti i prototipi.

Il tuo confusione nasce da una leggerissima fraintendimento della terminologia - entrambe le dichiarazioni e le definizioni possono includere prototipi (o meno):

void func(int a, char b, float c);

Questa è una funzione di Dichiarazione , che include un prototipo.

void func(int a, char b, float c) { /* ... */ }

Questa è una funzione di definizione , che include un prototipo.

"prototipo" e "non-prototipo" sono solo gli attributi di una funzione di tipo , ed entrambe le dichiarazioni e le definizioni introducono il tipo di funzione.

Così si può avere una dichiarazione, senza un prototipo:

void func();

o si può avere una definizione senza un prototipo (K & R stile C):

void func(a, b, c)
    int a;
    char b;
    float c;
{ /* ... */ }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top