Beim Überprüfen des Codes wende ich die folgenden Regeln an:
Verwenden Sie immer const
für Funktionsparameter, die als Referenz übergeben werden, wenn die Funktion die Daten, auf die verwiesen wird, nicht ändert (oder freigibt).
int find(const int *data, size_t size, int value);
Verwenden Sie immer const
für Konstanten, die andernfalls mit einem #define oder einer Enumeration definiert werden könnten. Dadurch kann der Compiler die Daten im Nur-Lese-Speicher (ROM) lokalisieren (obwohl der Linker in eingebetteten Systemen häufig ein besseres Werkzeug für diesen Zweck ist).
const double PI = 3.14;
Nie const in einer Funktion verwenden Prototyp für einen Parameter von übergeben
Wert . Es hat keine Bedeutung und ist daher nur "Lärm".
// don't add const to 'value' or 'size'
int find(const int *data, size_t size, const int value);
Verwenden Sie sie gegebenenfalls const volatile
an Orten, die vom Programm nicht geändert werden können, sich aber möglicherweise noch ändern. Hardware-Register sind hier der typische Anwendungsfall, zum Beispiel ein Statusregister, das einen Gerätezustand widerspiegelt:
const volatile int32_t *DEVICE_STATUS = (int32_t*) 0x100;
Andere Verwendungen sind optional. Zum Beispiel können die Parameter an eine Funktion in der Funktion Implementierung kann als const gekennzeichnet werden.
// 'value' and 'size can be marked as const here
int find(const int *data, const size_t size, const int value)
{
... etc
oder Funktion Rückgabewerte oder Berechnungen, die erhalten werden und sich dann nie ändern:
char *repeat_str(const char *str, size_t n)
{
const size_t len = strlen(str);
const size_t buf_size = 1 + (len * n);
char *buf = malloc(buf_size);
...
Diese Verwendungen von const
weisen lediglich darauf hin, dass Sie die Variable nicht ändern werden. Sie ändern nicht, wie oder wo die Variable gespeichert wird. Der Compiler kann natürlich feststellen, dass eine Variable nicht geändert wird, aber indem const
Sie sie hinzufügen, können Sie dies erzwingen. Dies kann dem Leser helfen und zusätzliche Sicherheit bieten (obwohl Sie möglicherweise andere Probleme haben, wenn Ihre Funktionen so umfangreich oder kompliziert sind, dass dies einen großen Unterschied ausmacht). Bearbeiten - zB. Eine dicht codierte 200-Zeilen-Funktion mit verschachtelten Schleifen und vielen langen oder ähnlichen Variablennamen, die weiß, dass sich bestimmte Variablen niemals ändern, kann das Verständnis erheblich erleichtern. Solche Funktionen wurden schlecht entworfen oder gewartet.
Probleme mit const
. Sie werden wahrscheinlich den Begriff "const Vergiftung" hören. Dies tritt auf, wenn das Hinzufügen const
zu einem Funktionsparameter die Ausbreitung von 'constness' verursacht.
Edit - const Vergiftung: zum Beispiel in der Funktion:
int function_a(char * str, int n)
{
...
function_b(str);
...
}
wenn wir ändern str
zu const
müssen wir dann dafür sorgen , dass fuction_b
auch ein nimmt const
. Und so weiter , wenn function_b
passiert das str
auf function_c
usw. Wie man sich vorstellen kann dies schmerzhaft sein könnte , wenn es viele einzelne Dateien / Module breitet sich in. Wenn es sich in eine Funktion ausbreitet, die nicht geändert werden kann (z. B. eine Systembibliothek), ist eine Umwandlung erforderlich. Wenn Sie also
const
in vorhandenem Code herumstreuen, müssen Sie vielleicht Ärger machen. In neuem Code ist es jedoch am besten, const
bei Bedarf eine konsistente Qualifizierung vorzunehmen .
Das heimtückischere Problem const
ist, dass es nicht in der Originalsprache war. Als Add-On passt es nicht ganz. Erstens hat es zwei Bedeutungen (wie in den obigen Regeln, was bedeutet "Ich werde das nicht ändern" und "Das kann nicht geändert werden"). Aber darüber hinaus kann es gefährlich sein. Kompilieren Sie diesen Code und führen Sie ihn aus. Je nach Compiler / Optionen kann er bei der Ausführung abstürzen:
const char str[] = "hello world\n";
char *s = strchr(str, '\n');
*s = '\0';
strchr
gibt a char*
nicht a zurück const char*
. Wie der Aufrufparameter ist
const
muss sie werfen den Aufrufparameter an char*
. In diesem Fall wird die eigentliche schreibgeschützte Speichereigenschaft verworfen. Bearbeiten: - Dies gilt im Allgemeinen für Variablen im Nur-Lese-Speicher. Mit "ROM" meine ich nicht nur das physische ROM, sondern jeden Speicher, der schreibgeschützt ist, wie es bei den Code-Abschnitten von Programmen unter einem typischen Betriebssystem der Fall ist.
Viele Standard-Bibliotheksfunktionen verhalten sich genauso, seien Sie also vorsichtig : Wenn Sie echte Konstanten haben (dh im ROM gespeichert sind), müssen Sie sehr vorsichtig sein, um ihre Konstanz nicht zu verlieren.
Specific issues with software development
. Ich bin ziemlich spezifisch.