Ricerca…


Confronto letterale e variabile

Supponiamo che tu stia confrontando il valore con alcune variabili

if ( i  == 2) //Bad-way
{
    doSomething;
}

Supponiamo ora di aver sbagliato == con = . Allora ci vorrà del tuo dolce momento per capirlo.

if( 2 == i) //Good-way
{
    doSomething;
}

Quindi, se un segno di uguale viene accidentalmente omesso, il compilatore lamenterà un "tentativo di assegnazione al letterale". Questo non ti proteggerà quando confronti due variabili, ma ogni piccolo aiuto è utile.

Vedi qui per maggiori informazioni.

Non lasciare vuoto l'elenco dei parametri di una funzione - usa nullo

Supponiamo che tu stia creando una funzione che non richiede argomenti quando viene chiamata e ti trovi di fronte al dilemma su come dovresti definire la lista dei parametri nel prototipo della funzione e nella definizione della funzione.

  • Hai la possibilità di mantenere l'elenco dei parametri vuoto sia per il prototipo che per la definizione. In tal modo, assomigliano all'istruzione di chiamata della funzione di cui avrete bisogno.

  • Si legge da qualche parte che uno degli usi della parola chiave void (ce ne sono solo alcuni), consiste nel definire l'elenco dei parametri delle funzioni che non accettano alcun argomento nella propria chiamata. Quindi, questa è anche una scelta.

Quindi, qual è la scelta giusta?

RISPOSTA: utilizzando la parola chiave void

CONSIGLI GENERALI: Se una lingua fornisce determinate funzionalità da utilizzare per uno scopo speciale, è meglio utilizzarlo nel codice. Ad esempio, utilizzando enum s anziché #define macro (che è per un altro esempio).

C11 sezione 6.7.6.3 "Dichiaratori di funzione", paragrafo 10, recita:

Il caso speciale di un parametro senza nome di tipo void come unica voce nell'elenco specifica che la funzione non ha parametri.

Il paragrafo 14 di quella stessa sezione mostra l'unica differenza:

... Una lista vuota in un dichiaratore di funzione che fa parte di una definizione di quella funzione specifica che la funzione non ha parametri. L'elenco vuoto in un dichiaratore di funzioni che non fa parte di una definizione di tale funzione specifica che non viene fornita alcuna informazione sul numero o sui tipi dei parametri.

Una spiegazione semplificata fornita da K & R (pagg. 72-73) per le cose di cui sopra:

Inoltre, se una dichiarazione di funzione non include argomenti, come in
double atof(); , anche questo è inteso nel senso che nulla deve essere assunto riguardo agli argomenti di atof ; tutto il controllo dei parametri è disattivato. Questo speciale significato dell'elenco di argomenti vuoti ha lo scopo di consentire ai vecchi programmi in C di compilare con nuovi compilatori. Ma è una cattiva idea usarlo con nuovi programmi. Se la funzione accetta argomenti, dichiarali; se non accetta argomenti, usa void .

Ecco come dovrebbe apparire il prototipo della tua funzione:

int foo(void);

Ed ecco come dovrebbe essere la definizione della funzione:

int foo(void)
{
    ...
    <statements>
    ...
    return 1;
}

Un vantaggio nell'usare il suddetto tipo di dichiarazione int foo() (cioè senza utilizzare la parola chiave void ), è che il compilatore può rilevare l'errore se si chiama la propria funzione usando un'istruzione errata come foo(42) . Questo tipo di istruzione di chiamata a una funzione non causerebbe errori se si lascia vuota l'elenco dei parametri. L'errore passerebbe silenziosamente, inosservato e il codice continuerebbe a essere eseguito.

Questo significa anche che dovresti definire la funzione main() questo modo:

int main(void)
{
    ...
    <statements>
    ...
    return 0;
}

Si noti che anche se una funzione definita con un elenco di parametri vuoto non accetta argomenti, non fornisce un prototipo per la funzione, quindi il compilatore non si lamenterà se la funzione viene successivamente chiamata con argomenti. Per esempio:

#include <stdio.h>

static void parameterless()
{
    printf("%s called\n", __func__);
}

int main(void)
{
    parameterless(3, "arguments", "provided");
    return 0;
}

Se quel codice è salvato nel file proto79.c , può essere compilato su Unix con GCC (versione 7.1.0 su macOS Sierra 10.12.5 usato per la dimostrazione) in questo modo:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -pedantic proto79.c -o proto79
$

Se compili con opzioni più stringenti, ottieni degli errori:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -pedantic proto79.c -o proto79 
proto79.c:3:13: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
 static void parameterless()
             ^~~~~~~~~~~~~
proto79.c: In function ‘parameterless’:
proto79.c:3:13: error: old-style function definition [-Werror=old-style-definition]
cc1: all warnings being treated as errors
$

Se assegni alla funzione il prototipo formale static void parameterless(void) , la compilazione restituisce errori:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -pedantic proto79.c -o proto79 
proto79.c: In function ‘main’:
proto79.c:10:5: error: too many arguments to function ‘parameterless’
     parameterless(3, "arguments", "provided");
     ^~~~~~~~~~~~~
proto79.c:3:13: note: declared here
 static void parameterless(void)
             ^~~~~~~~~~~~~
$

Morale: assicurati sempre di avere dei prototipi e assicurati che il compilatore ti dica quando non stai obbedendo alle regole.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow