C Language
Gemeenschappelijke C-programmeer-idioom en ontwikkelaarspraktijken
Zoeken…
Letterlijk en variabel vergelijken
Stel dat u waarde vergelijkt met een variabele
if ( i == 2) //Bad-way
{
doSomething;
}
Stel nu dat u zich vergist heeft ==
met =
. Dan zal het je zoete tijd kosten om erachter te komen.
if( 2 == i) //Good-way
{
doSomething;
}
Als een gelijkteken per ongeluk wordt weggelaten, zal de compiler klagen over een "poging tot letterlijke toewijzing". Dit beschermt je niet bij het vergelijken van twee variabelen, maar elk klein beetje helpt.
Kijk hier voor meer info.
Laat de parameterlijst van een functie niet leeg - gebruik void
Stel dat u een functie maakt waarvoor geen argumenten nodig zijn wanneer deze wordt aangeroepen en dat u wordt geconfronteerd met het dilemma hoe u de parameterlijst in het functieprototype en de functiedefinitie moet definiëren.
U hebt de keuze om de parameterlijst leeg te houden voor zowel prototype als definitie. Daardoor lijken ze precies op de functie-aanroepinstructie die u nodig hebt.
Je leest ergens dat een van de toepassingen van het trefwoord void (er zijn er maar een paar), het definiëren van de parameterlijst met functies is die geen argumenten in hun aanroep accepteren. Dus dit is ook een keuze.
Dus wat is de juiste keuze?
ANTWOORD: het trefwoord void gebruiken
ALGEMEEN ADVIES: Als een taal bepaalde functies biedt die u voor een speciaal doel kunt gebruiken, kunt u dat beter in uw code gebruiken. Gebruik bijvoorbeeld enum
s in plaats van #define
macro's (dat is voor een ander voorbeeld).
C11 paragraaf 6.7.6.3 "Functie declarators", paragraaf 10, bepaalt:
Het speciale geval van een naamloze parameter van het type void als het enige item in de lijst geeft aan dat de functie geen parameters heeft.
Alinea 14 van diezelfde paragraaf laat het enige verschil zien:
… Een lege lijst in een functie-declarator die deel uitmaakt van een definitie van die functie geeft aan dat de functie geen parameters heeft. De lege lijst in een functie-declarator die geen deel uitmaakt van een definitie van die functie geeft aan dat er geen informatie over het aantal of de typen parameters wordt verstrekt.
Een vereenvoudigde uitleg van K&R (pgs- 72-73) voor de bovenstaande dingen:
Als een functieverklaring bovendien geen argumenten bevat, zoals in
double atof();
dat betekent ook dat niets mag worden verondersteld over de argumenten vanatof
; alle parametercontrole is uitgeschakeld. Deze speciale betekenis van de lege lijst met argumenten is bedoeld om oudere C-programma's te laten compileren met nieuwe compilers. Maar het is een slecht idee om het te gebruiken met nieuwe programma's. Als de functie argumenten aanneemt, verklaar ze; als het geen argumenten nodig heeft, gebruik danvoid
.
Dus dit is hoe uw functieprototype eruit moet zien:
int foo(void);
En zo zou de functiedefinitie moeten zijn:
int foo(void)
{
...
<statements>
...
return 1;
}
Een voordeel van het gebruik van het bovenstaande, in plaats van het type int foo()
(dwz zonder het trefwoord void te gebruiken ), is dat de compiler de fout kan detecteren als u uw functie aanroept met een foutieve verklaring zoals foo(42)
. Dit soort functieoproepinstructie zou geen fouten veroorzaken als u de parameterlijst leeg laat. De fout zou stil, onopgemerkt voorbijgaan en de code zou nog steeds worden uitgevoerd.
Dit betekent ook dat u de functie main()
als volgt moet definiëren:
int main(void)
{
...
<statements>
...
return 0;
}
Merk op dat hoewel een functie gedefinieerd met een lege parameterlijst geen argumenten aanneemt, het geen prototype voor de functie biedt, dus de compiler zal niet klagen als de functie vervolgens met argumenten wordt aangeroepen. Bijvoorbeeld:
#include <stdio.h>
static void parameterless()
{
printf("%s called\n", __func__);
}
int main(void)
{
parameterless(3, "arguments", "provided");
return 0;
}
Als die code is opgeslagen in het bestand proto79.c
, kan deze op Unix worden gecompileerd met GCC (versie 7.1.0 op macOS Sierra 10.12.5 gebruikt voor demonstratie) als volgt:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -pedantic proto79.c -o proto79
$
Als u compileert met strengere opties, krijgt u fouten:
$ 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
$
Als u de functie het formele prototype static void parameterless(void)
, geeft de compilatie fouten:
$ 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)
^~~~~~~~~~~~~
$
Moraal - zorg er altijd voor dat u prototypes hebt en zorg ervoor dat uw compiler u vertelt wanneer u zich niet aan de regels houdt.