Hilfe & Service von EDV-Fachleuten
cpp0a0.png

Edit v4.000 from 2005-03-29 to 2020-06-24 by HSc+SBa+TSc

Konventionen für C++

Wollen Sie im Team programmieren, sind Regeln der Zusammenarbeit gefragt. Eine ist die Schreibweise von Variablen und Objekten in Quelltexten. Wie diese bei H&S<-EDV erfolgt, wird nachfolgend beschrieben. Dieser Artikel ist noch nicht fertig und wird von Zeit zu Zeit fortgesetzt!

Konvention für den Aufbau von Quelltexten in Die Benennung mittels [Präfix] Typkürzel [Basisname [Suffix]]

Edit v4.000 from 2005-03-29 to 2020-06-24 by HSc+SBa+TSc

Konventionen für den Aufbau von Quelltexten

Header und Source

Das Tolle bei C und C++ ist, das es eine klare Trennung zwischen Deklaration (Header) und Implementation (Source) gibt. Diese Trennung kann man sich für viele Vorteile zunutze machen.

Prinzipiell gilt, zu jeder C bzw. CPP-Datei sollte es auch eine H bzw. HPP-Datei geben. Zudem sollte man auch nur Header inkludieren. Die Header selbst sollten so wenig wie möglich andere Header inkludieren, siehe Stichwort Forward declaration. Wenn man dies beachtet, hat man bereits viel gewonnen. Hier einige Beispiele warum, weshalb, wieso:

  • Source-Dateien müssen nicht inkludiert werden (Wer macht sowas?).
  • Vermeidung eines Chaos mit dem Schlüsselwort extern, d.H. (ja ein schlechtes, gesponnenes Beispiel) wenn man 30 globale Variablen nutzen möchte und diese keine Deklaration in einer Header-Datei haben, müssen diese 30 Variablen jedes Mal mit extern benannt werden. Noch schlimmer, wenn man 3 dieser Variablen aus irgendeinen Grund vom Aufbau her ändern muss, dann muss diese Änderung an jeder Stelle vorgenommen werden, wo die Variable benutzt wird.
    Stattdessen: Eine Header-Datei mit den gewünschten Variablen als "extern" deklarieren. In der gleichnamigen Source-Datei diese implementieren, bzw. initialisieren. Dann braucht man nur noch den entsprechenden Header inkludieren und kann auf diese Variablen direkt zugreifen.
  • Vorteile bei der Geschwindigkeit des Compilers und Linkers, vor allem spürbar, wenn Mehrkern-Kompilierung möglich und aktiviert ist.
  • Besseres Projektmanagement. Der "Vorgesetzte" in einer Gruppe von Programmierern, könnte z.B. mittels der Header-Dateien schon die Struktur vorgeben. Die Programmierer können dann die Implementation der Funktionskörper delegiert bekommen, bzw. unter sich aufteilen.

Header Input Process Output (HIPO)

Sie ist eine der ersten Art und Weisen, wie Quelltexte dokumentiert werden sollen.

In C++ lässt sich dieses Verfahren immer noch anwenden. Allerdings schreibt man diese besser nicht mehr in die Source-Dateien, sondern in die Header-Dateien. Der Grund dafür ist folgender, da in Header-Dateien im Prinzip die Schnittstellen definiert werden, kann man dort auch den HIPO-Kommentar hinschreiben. Die Header beschreiben quasi genau das gleiche, was wir mit den HIPO-Kommentaren machen. In den Source-Dateien schreibt man dann nur noch die Kommentare innerhalb einer Funktion. Zu jeder Source-Datei sollte es immer eine Header-Datei geben.

Vorteil
  • Sie ist in jeder IDE anwendbar. Im Zweifelsfall kann man diese auch in einem einfachen Editor wie Notepad immer noch lesen.
  • Sie funktioniert komplett manuell, d.H. auch ohne IDE kann man diese benutzen.
  • Die Dokumentation/Kommentation ist zusammen mit dem Programmcode an einem Ort (Lokalität).
  • Die Erläuterung, was der folgende Quelltext realisieren soll, was er übergeben bekommt, was er intern gebraucht und was er zurückgibt, steht direkt vor dem Quelltext!
Nachteil: Sie streckt den Quelltext, allerdings lassen diese sich in moderneren Entwicklungsumgebungen auf und zuklappen.
Als zusätzlicher Nutzen ergibt sich daraus
  • abgegrenzte Funktionen,
  • einfache Datenschnittstelle und
  • Geheimhaltung der Wirkungsweise durch Übergabe der Art und Weise des Funktionsaufrufs und den Kommentarkopf.
Beispiel:
/******************************************************************************
 * Dateigroesze ermitteln durch                                               *
 * - Sichern der aktuellen Position,                                          *
 * - Springen zum Dateiende um die Groesze auszulesen und                     *
 * - Zuruecksprung zur gesicherten aktuellen Positon.                         *
 * Edit v1.102 from 2009-06-05 to 2009-09-21 by HSc+TSc                       *
 * -------------------------------------------------------------------------- *
 * Input                                                                      *
 * - pZeiger: Dateizeiger.                                                    *
 * Process                                                                    *
 * + Variablen                                                                *
 * - ulgDatei: Angestrebte Zielgroesze fuer die Datei.                        *
 * - intAnzahl: Eingegebenen Anzahl von Einheiten, die geschrieben werden     *
 *   sollen.                                                                  *
 * - intEinheit: Ausgewaehlte Groesze der Einheit.                            *
 * - intI: Zaehler.                                                           *
 * - intL: Laenge.                                                            *
 * - intP: Position.                                                          *
 * - strAnzahl: Inhalt des Editfeldes Anzahl,                                 *
 *   welche in eine Zahl umgewandelt werden soll.                             *
 * - strEinheit: Inhalt des Editfeldes Einheit,                               *
 *   welche in eine Zahl umgewandelt werden soll.                             *
 * Output                                                                     *
 * - ulgDatei.                                                                *
 ******************************************************************************/
unsigned long filesize(void * pZeiger)
{
 …

Einrückung mit Tabulatoren

Sehr lange Zeit haben wir für die Einrückung pro Ebene ein Leerzeichen verwendet. Hauptsächlich aufgrund von Limitierungen der Zeichen pro Zeile. Jetzt haben wir es bereits 2020 und die Technik hat sich massiv weiterentwickelt. Effizienter ist es mit Tabulatoren einzurücken, weil:

  • Die Breite eines Tabulators kann in allen Entwicklungsumgebungen eingestellt werden (jeder hat einen anderen Geschmack).
  • Wenn der Code (aus welchen Gründen auch immer) wieder auf Leerzeichen-Einrückung umgewandelt werden muss, kann man diesen sehr leicht wieder auf ein einzelnes Leerzeichen zurückführen. Dies entspricht dann auch wieder unseren klassischen Einrückung.
  • Klare Trennung von Tabulator = Einrückung und Leerzeichen = Leerzeichen in einem String.
  • Die meisten Editoren nehmen Tabulatoren ohne weitere Einstellungen an. Diese machen sich sogar oft die Tabulatoren zunutze und rücken automatisch ein, wenn man einen neuen "Block" {} schreibt.

Edit v4.000 from 2005-03-29 to 2020-06-24 by HSc+SBa+TSc

Benennung

Der Name von Konstanten, Variablen und Objekten hat die Aufgabe diese zu beschreiben. Es sollte aber nicht die maximale Größe von 240 Zeichen pro Name ausgenutzt werden. Der Seitenrand eines Blattes Papier im Format A4 und bei einer Schriftgröße von 10, ist bei 80 Zeichen pro Zeile auch ausgereizt. Es sollte nicht mehr als ein Name pro Zeile stehen. Ein Kompromiss ist irgendwo zwischen 8 und 16 Zeichen pro Name zu finden.

Die ungarische Notation, welche auch von namhaften Herstellern verwendet wird, wurde mit Einführung der objektorientierten Programmierung, durch Reddick für Visual Basic überarbeitet. An diese angelehnt sind die Vorgaben, die in der Firma "H&S<-EDV" für diese gelten.

Die grundsätzliche Form der ungarischen Notation ist: [Präfix] Typkürzel [Basisname [Suffix]]
Anhand der Präfixe, Typbezeichnung und eventuellem Suffix von Konstanten, Variablen und Objekten, erkennt man, ohne nach der Deklaration der selbigen suchen zu müssen, von welchen Datentyp diese sein sollte und wofür diese eingesetzt wird.


Variablen

Zuerst kommt der Präfix (optional) mit dem entsprechenden Typkürzel. Der Basisname der Variable wird englisch geschrieben, da Englisch die Weltsprache ist und heutzutage viele Programmierer in Teams aus verschiedenen Ländern stammen. Der Basisname beginnt immer mit einem großen Anfangsbuchstaben, ebenso der Suffix, welcher direkt an den Basisnamen angefügt wird. Vom Gesamtbild her sind die Variablennamen nach dem lower camel case-Prinzip (halloSchoenesWetterHeute) aus Java verkettet.

Zum Bsp. die Variable für die Anzahl der € als Ganzzahl ohne Vorzeichen (unsigned int) könnte uiEuroCount mit
  • der Typ uiEuroCount für unsigned int
  • dem Name der Variable uiEuroCount für € und
  • dem Suffix uiEuroCount für die Anzahl.

Präfixe

Noch nicht begonnen...

Typbezeichnungen

Noch nicht fertig... Mit den Typbezeichnungen kann man den Datentyp direkt aus dem Variablennamen herauslesen. Dies ist sehr praktisch, da man so nicht zur Deklaration der Variable springen muss. In der folgenden Tabelle sehen Sie eine Übersicht vieler Datentypen und deren Kürzel, die wir als Typbezeichnungen für unsere Variablen verwenden.

Typ Kürzel Länge / Darstellung Wertebereich / Anmerkung Beispiel
Primitive Typen (allgemein)
bool b Plattformabhängig, d.h. die Länge hängt von der CPU−Architektur ab. 0 = false (falsch)
1 = true (wahr)
bool bStatus = false;
auto bSchalter = true;
char8_t c8 genau 8 Bit, für UTF-8 (ab 2020) -127128 char8_t c8Symbol = u8'A';
auto c8Zeichen = u8'?';
char16_t c16 genau 16 Bit, für UTF-16 -32.76832.767 char16_t c16Symbol = u'A';
auto c16Zeichen = u'?';
char32_t c32 genau 32 Bit, für UTF-32 -2.147.483.6482.147.483.647 char32_t c32Symbol = U'A';
auto c32Zeichen = U'?';
char c
ac
genau 8 Bit Signed: -127128
Unsigned: 0255
'1', 'a', '~'
char cZeichen = 'A';
auto acSymbol = '?';
wchar_t c
wc
16 Bit (Windows) oder 32 Bit Signed: -32.76832767
Unsigned: 065.535
L'1', L'a', L'~'
wchar_t cZeichen = L'A';
auto wcSymbol = L'?';
Primitive Ganzzahlen
short
short int
signed short
signed short int
unsigned short
unsigned short int
s mindestens 16 Bit Signed: -32.76832.767
Unsigned: 065.535
short sZahl = ((short)13);
auto sNummer = static_cast<unsigned short>(42u);
int
signed
signed int
unsigned
unsigned int
i mindestens 16 Bit, generell 32 Bit Signed: -2.147.483.6482.147.483.647
Unsigned: 04.294.967.295
unsigned int uiGroesze = 23u;
auto iZahl = 42;
long
long int
signed long
signed long int
unsigned long
unsigned long int
l mindestens 32 Bit Signed: -2.147.483.6482.147.483.647
Unsigned: 04.294.967.295
unsigned long ulAnzahl = 3466ul;
auto lNummer = 32539l;
long long
long long int
signed long long
signed long long int
unsigned long long
unsigned long long int
ll mindestens 64 Bit Signed: -9.223.372.036.854.775.8089.223.372.036.854.775.807
Unsigned: 018.446.744.073.709.551.615
unsigned long long ullGefunden = 63ull;
auto llAnzahl = 32434635ll;
Primitive Gleitkommazahlen
float f genau 32 Bit ±1,18×10−38±3,4×1038, (circa 7 Dezimalziffern) +0, −0, +∞, −∞ und verschiedene Bitmuster für NaN's float fPi = 3.14159265359f;
auto fEuler = 2.7182818284f;
double d genau 64 Bit ±2,23×10−308±1,80×10308, (circa 16 Dezimalziffern) +0, −0, +∞, −∞ und verschiedene Bitmuster für NaN's double dPi = 3.14159265359;
auto dEuler = 2.7182818284;
long double ld Compiler- und Plattformabhängig, meistens 80 Bit auf x86/64.
Auf Windows (64Bit) identisch zu double (getestet)
±3,65×10−4951±1,18×104932, (circa 18 Dezimalziffern) +0, −0, +∞, −∞ und verschiedene Bitmuster für NaN's long double ldPi = 3.14159265359l;
auto ldEuler = 2.7182818284l;
Zeichenketten
char name[n]
wchar_t name[n]
stf Vielfache von 8 oder 16 Bit multipliziert mit der Länge n Jedes Zeichen jeweils 0255 (00hFFh) für char, bzw. 065535 (0000hFFFFh) für wchar_t
"Hallo", L"Hallo"
char name[4] = "TSc";
wchar_t name[4] = L"TSc";
char *
wchar_t *
str Vielfache von 8 oder 16 Bit bis zum Nullbyte char * name = "TSc";
wchar_t * name = L"TSc";
std::string
std::wstring
str Vielfache von 8 oder 16 Bit mit einstellbarer, oder anhand Nullbyte automatisch erkannter Länge std::string name = "TSc";
std::wstring name = L"TSc";
Objekte, Instanzen, Zeiger und Handles
In Arbeit...
Grafische Bedienelemente (z.B. QT und wxWidgets)
QPushButton
wxButton
btn Eine Schaltfläche, die mit Maus, Tastatur und Antipp-Touchscreen-Geste gedrückt werden kann und dabei ein vom Programmierer festgelegtes Ereignis auslöst. auto btnStart = new QPushButton("Start", this);
auto btnStart = new wxButton(this, wxID_ANY, L"Start");
In Arbeit...

Suffixe

Noch nicht begonnen...

Nach Oben