Szukaj…


Porównywanie literału i zmiennej

Załóżmy, że porównujesz wartość z jakąś zmienną

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

Załóżmy teraz, że pomyliłeś == z = . Wtedy zajmie ci słodki czas, aby to rozgryźć.

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

Następnie, jeśli przypadkowo pominięto znak równości, kompilator narzeka na „próbę przypisania literału”. To nie ochroni cię podczas porównywania dwóch zmiennych, ale każda odrobina pomaga.

Zobacz tutaj, aby uzyskać więcej informacji.

Nie pozostawiaj pustej listy parametrów funkcji - użyj void

Załóżmy, że tworzysz funkcję, która nie wymaga żadnych argumentów podczas jej wywoływania, i stajesz przed dylematem, jak należy zdefiniować listę parametrów w prototypie funkcji i jej definicji.

  • Możesz pozostawić pustą listę parametrów zarówno dla prototypu, jak i definicji. W ten sposób wyglądają tak, jak potrzebna będzie instrukcja wywołania funkcji.

  • Czytasz gdzieś, że jednym z zastosowań słowa kluczowego void (jest tylko kilka), jest zdefiniowanie listy parametrów funkcji, które nie przyjmują żadnych argumentów w swoim wywołaniu. To także jest wybór.

Więc jaki jest właściwy wybór?

ODPOWIEDŹ: użycie słowa kluczowego void

WSKAZÓWKI OGÓLNE: Jeśli język udostępnia pewne funkcje do specjalnych celów, lepiej użyć tego w swoim kodzie. Na przykład użycie enum s zamiast #define makra (to na inny przykład).

C11 sekcja 6.7.6.3 „Deklaratory funkcji”, akapit 10, stwierdza:

Szczególny przypadek nienazwanego parametru typu void jako jedynej pozycji na liście określa, że funkcja nie ma parametrów.

Paragraf 14 tej samej sekcji pokazuje jedyną różnicę:

… Pusta lista w deklaratorze funkcji, która jest częścią definicji tej funkcji, określa, że funkcja nie ma parametrów. Pusta lista w deklaratorze funkcji, która nie jest częścią definicji tej funkcji, określa, że nie podano informacji o liczbie lub typach parametrów.

Uproszczone wyjaśnienie przedstawione przez K&R (str. 72–73) dla powyższych elementów:

Ponadto, jeśli deklaracja funkcji nie zawiera argumentów, jak w
double atof(); , to również oznacza, że nie można nic zakładać o argumentach atof ; wszystkie sprawdzanie parametrów jest wyłączone. To specjalne znaczenie pustej listy argumentów ma na celu umożliwienie starszym programom C kompilacji z nowymi kompilatorami. Ale to zły pomysł, aby używać go z nowymi programami. Jeśli funkcja przyjmuje argumenty, zadeklaruj je; jeśli nie przyjmuje żadnych argumentów, użyj void .

Tak powinien wyglądać prototyp funkcji:

int foo(void);

I taka powinna być definicja funkcji:

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

Jedną z zalet używania powyższego, w porównaniu z deklaracją typu int foo() (tj. Bez użycia słowa kluczowego void ), jest to, że kompilator może wykryć błąd, jeśli wywołasz funkcję za pomocą błędnej instrukcji, takiej jak foo(42) . Tego rodzaju instrukcja wywołania funkcji nie spowoduje żadnych błędów, jeśli pozostawisz listę parametrów pustą. Błąd minąłby cicho, nie wykryty, a kod nadal byłby wykonywany.

Oznacza to również, że należy zdefiniować funkcję main() następujący sposób:

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

Zauważ, że chociaż funkcja zdefiniowana z pustą listą parametrów nie przyjmuje żadnych argumentów, nie zapewnia prototypu dla funkcji, więc kompilator nie będzie narzekał, jeśli funkcja zostanie następnie wywołana z argumentami. Na przykład:

#include <stdio.h>

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

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

Jeśli ten kod jest zapisany w pliku proto79.c , można go skompilować w systemie Unix za pomocą GCC (wersja demonstracyjna 7.1.0 na macOS Sierra 10.12.5):

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

Jeśli kompilujesz przy użyciu bardziej rygorystycznych opcji, pojawiają się błędy:

$ 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
$

Jeśli nadasz tej funkcji formalny prototyp static void parameterless(void) , wówczas kompilacja da błędy:

$ 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)
             ^~~~~~~~~~~~~
$

Moralność - zawsze upewnij się, że masz prototypy i upewnij się, że Twój kompilator poinformuje Cię, gdy nie będziesz przestrzegać reguł.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow