2015-07-24 10 views
6

Poiché la funzione printf restituisce un valore intero ogni volta che viene utilizzato (il numero di caratteri scritti sullo schermo), non dovrebbe essere obbligatorio memorizzare questo valore in una variabile int ogni volta che viene chiamato printf?Perché non scriviamo int x = printf ("testo"); poiché l'istruzione printf() restituisce un valore intero ogni volta?

Edit:

Se una funzione restituisce certo valore, perché non c rendono necessario per memorizzare il valore al momento della chiamata di funzione?

+2

Sei libero di fare lo stesso. –

+0

E cosa faresti con quel numero? – jonrsharpe

+1

Ho compilato il codice, non ho ricevuto alcun errore o avviso sul valore restituito non utilizzato. Che compilatore stai usando, e qual è l'errore? – Barmar

risposta

1

Se si pensa che il programma C verrà tradotto in un linguaggio assembly (ad esempio l'assembly x86), la lettura del valore restituito di una funzione è solo una questione di lettura del valore memorizzato nel registro "eax" di la tua CPU.

Il linguaggio di programmazione C è stato scritto storicamente per essere un linguaggio semplice da analizzare e compilare su un computer PDP-11 molto limitato (per gli standard odierni).

precoce compilatori C (beh, alcuni di loro) funzioni dichiarate senza un tipo di ritorno e senza un ritorno accettato, come la seguente:

myFunc(int *x) 
{ 
    *x = *x + *x; 
} 

Questa è una funzione che quei compilatori primi C interpretano come

int myFunc(int *x) 
{ 
    *x = *x + *x; 
    return 0; 
} 

Quindi la risposta alla tua domanda può essere "a causa del codice legacy".

Ci sono comunque situazioni in cui il valore di ritorno deve o deve essere controllato.

La regola 16.10 delle linee guida MISRA C afferma che: "Se una funzione restituisce informazioni di errore, devono essere verificate le informazioni di errore".

Quindi, se è necessario assicurarsi che printf() abbia stampato qualcosa, se si sta utilizzando il valore restituito come "informazione di errore", seguendo le linee guida MISRA, è necessario verificare tale valore.

+0

I compilatori C iniziali utilizzavano la regola implicita int perché erano basati su B, che aveva solo un tipo di dati. Questo è probabilmente il motivo per cui la parola chiave auto esiste ancora. –

3

Può essere, solo se necessario.

Se al numero non interessa non si desidera utilizzare il valore restituito. non serve archiviare lo stesso.

+0

Ma se ho una mia funzione che restituisce un valore int, e mentre lo chiamo non lo faccio memorizza lo stesso, il compilatore restituisce un errore. Perché non vale lo stesso per printf()? – n00b

+1

@ n00b 'il compilatore restituisce un errore. ... no non lo farà. Può, con un controllo molto rigoroso, emettere un avviso per "ignorare" il valore di ritorno e si può avere "-Werror" abilitato. –

+0

Sì, ho capito. Non dà errori, ho solo pensato che dovrebbe dare un errore, dal momento che la funzione restituisce un valore int, e io non sto usando il valore. Colpa mia. – n00b

2

Se avete un idea di come si intende utilizzare x poi, naturalmente, si può scrivere

int x = printf("text"); 

In caso contrario, il valore di ritorno della funzione viene semplicemente scartato perché non viene utilizzato.

E nella maggior parte dei casi i programmatori non trovano un'applicazione utile del valore di ritorno di printf.

Tuttavia a volte può essere utilizzato ad esempio per stampare tabelle con colonne allineate.

Ad esempio

int n = printf("%s", SomeString); 

if (n < COLUMN_WIDTH) printf("%*c", COLUMN_WIDTH - n, ' '); 

Considerate questo semplice programma

#include <stdio.h> 

int main(void) 
{ 
    const int COLUMN_WIDTH = 20; 

    int n = printf("%s", "Hello"); 
    if (n < COLUMN_WIDTH) printf("%*c", COLUMN_WIDTH - n, ' '); 
    printf("%s", "World"); 
} 

La sua uscita è

Hello    World 

Ecco un altro esempio in cui il valore restituito di printf trova un'utile applicazione.

Supponiamo che è necessario per produrre una sequenza di numeri separati da una virgola, come per esempio

1, 2, 3, 4, 5, 6, 7, 8, 9 

Come uscita una tale sequenza utilizzando solo un singolo ciclo senza porre dichiarazioni di stampa di fuori del ciclo?

Ecco un programma che mostra come può essere fatto basandosi sull'uso del valore di ritorno della funzione printf. :) Provalo.

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

int main(void) 
{ 
    size_t n = 0; 

    printf("Enter the number of elements in the array (greater than 0): "); 
    scanf("%zu", &n); 

    if (n == 0) exit(1); 

    int a[n]; 

    srand((unsigned int)time(NULL)); 

    size_t i; 

    for (i = 0; i < n; i++) a[ i ] = rand() % n; 

    i = 0; 

    do 
    { 
     printf("%d", a[ i ]); 
    } while (++i < n && printf(", ") > 0); 

    return 0; 
} 

Per quanto riguarda il programma di

int foo(int x) { 
    return x; 
} 
int main() { 
    foo(10); 
} 

quindi funzione foo chiamante non ha alcun effetto. Non fa nulla e infatti può essere rimosso. E non tutti i compilatori pubblicano un messaggio per il tuo programma. Sembra che il compilatore che stai usando abbia un'opzione di compilazione che prevede che il compilatore consideri avvertenze come errori. Quindi il tuo compilatore vuole che tu presti attenzione al fatto che la chiamata della funzione non ha alcun effetto. È possibile che tu abbia commesso un errore logico.

D'altra parte la funzione di chiamata printf ha un effetto visibile.

+0

@ n00b Vedere il mio post aggiornato. –

+0

Sì, mi dispiace. Ho modificato di nuovo la domanda. Quello che voglio veramente sapere è perché C non rende obbligatorio memorizzare il valore restituito da una funzione? – n00b

+0

@ n00b Vedere un altro post. :) –

1

È possibile memorizzare il valore restituito se necessario, ad esempio per assicurarsi che si stia emettendo il numero desiderato di caratteri (sembra molto improbabile che uno abbia questa necessità, soprattutto considerando che nella produzione di solito si dispone di una visione più completa moduli di registrazione per gestire le uscite).

È possibile anche esplicitamente dire che non si cura di quel valore di ritorno al compilatore con un (void) come in

(void) printf("hello world\n"); 

Si noti che questo non ha implicazioni altro che sopprimere avvertimenti di alcuni strumenti (ad esempio, lint

1

Se una funzione restituisce un determinato valore, perché C non rende necessario memorizzare il valore al momento della chiamata di funzione?

Questo è probabilmente peggiore dal normale C punto di stile di vista della programmazione: È stata creata una variabile locale con un valore, ma non usarlo:

int x; 
    x = printf(...); 

darebbe un avvertimento che non stai usando x per niente. Si dovrebbe fare questo per risolvere entrambi i fine aperti:

if (printf(...)<EXPECTED_OUTPUT_BYTES) exit(1); 

o simile. Fortunatamente, l'uscita non restituisce nulla.

0

Come altri hanno già detto, sei libero di ignorare il risultato di qualsiasi chiamata di funzione.

Tuttavia, se si utilizza gcc, è possibile aggiungere un attributo di funzione warn_unused_result che fa sì che gcc avvisi se il risultato di una funzione non viene utilizzato. Combina questo con -Werror e poi verifica che i risultati vengano utilizzati.

Ecco l'esempio dalla pagina di informazioni gcc:

int fn() __attribute__ ((warn_unused_result)); 
int foo() 
{ 
    if (fn() < 0) return -1; 
    fn(); 
    return 0; 
} 

Ciò mettere in guardia (o errore -Werror) circa l'uso di fn();.