Ein Angebot von

Fünf praxisnahe C/C++-Tipps für Embedded-Software-Programmierer

| Redakteur: Sebastian Gerstl

Wer den Umgang mit C++ bei der Entwicklung von Embedded Software vertiefen möchte, sollte sich mit diese bewährten Tipps aus der Programmierungs-Praxis auseinandersetzen.
Wer den Umgang mit C++ bei der Entwicklung von Embedded Software vertiefen möchte, sollte sich mit diese bewährten Tipps aus der Programmierungs-Praxis auseinandersetzen. (Bild: gemeinfrei / CC0)

Es ist Zeit für ein paar weitere, hoffentlich hilfreiche Tipps für Embedded-Software-Entwickler. Diese Tipps sind in vielen Fällen nur gesunder Menschenverstand, aber ich denke, wir müssen sie uns immer mal wieder in Erinnerung rufen.

Bereits zweimal zuvor haben wir hier auf embedded-software.engineer jeweils fünf praxisnahe Tipps für den Einsatz von C- und C++-Programmierung von Embedded Software aufgelistet. Denn in der Praxis offenbaren sich oft noch einige Tücken, die einem beim Erlernen der Programmiersprache vielleicht nicht bewusst geworden sind. Colin Walls, Embedded-Software-Technologist bei Mentor, hat erneut in seinem Erfahrungsschatz gewühlt und hält erneut Programmiertipps für Embedded-Software-Programmierung parat.

In C/C++ sollten Sie Klammern ({ }), sowohl öffnende als auch schließende, immer auf die Zeilen selbst setzen und ein entsprechendes Paar horizontal ausrichten

Da in C/C++ Leerzeichen für den Compiler keine Rolle spielen, liegt das Layout des Codes ganz beim Programmierer. Colins erste Programmierregel lautet: „schreibe Code mit Blick auf den Anwender“. Deshalb ist es wichtig, dass man das Layout richtig gestaltet. In einer strukturierten Programmiersprache ist die Hierarchie entscheidend – genau das, worauf es zum Beispiel bei einem „if“ ankommt. Sie könnten Code wie diesen schreiben:

if (a == b) {
   x = y;
   y = x; }

Die Einrückung ist korrekt, aber meiner Meinung verdeutlicht der zusätzliche vertikale Leerraum um den Block herum dies besser:

if (a == b)
{
   x = y;
   y = x;
}

Selbst wenn Sie eine Funktion in C/C++ einfügen, wird der Compiler wahrscheinlich eine Out-of-line-Kopie erstellen

Die Möglichkeit, eine Funktion einzufügen, so dass der Aufruf einer Funktion durch den tatsächlichen Funktionscode ersetzt wird, ist ein praktischer Weg, um die Performance des Codes zu verbessern, auch wenn es nur für kleine Funktionen sinnvoll ist. Mit den richtigen Optionen für die Kompilierungszeit oder einem Hinweis, der dem Compiler mit Hilfe des inline-Schlüsselworts gegeben wird, geschieht dies automatisch. Vorsicht ist geboten, da ein Compiler auch eine Out-of-line-Kopie des Codes erstellen kann. Das kann zwei Gründen haben:

  • 1. Einige Debugger sind nicht intelligent genug, um mit eingebundenem Code umgehen zu können. Diese benötigen zur Debug-Zeit eine Out-of-line-Kopie.
  • 2. Wenn die Funktion global ist, kann sie in anderen Modulen verwendet werden, in denen der Compiler keinen Zugriff auf den Code hat, um ihn einzubinden.

Die Lösung für (1) ist eine Frage der Toolchain-Auswahl. (2) kann man lösen, indem man eine solche Funktion als statisch deklariert.

Auch wenn eine Zuweisung in C/C++ einen Wert ergibt, ist es sehr schlechte Praxis, einen solchen in einen Ausdruck einzubetten

Ich erinnere mich noch, als ich mich vor vielen Jahren zum ersten Mal mit C beschäftigte: Es war eine ziemliche Offenbarung, als ich verstand, dass eine Zuweisung nur ein Ausdruck war und ein Ausdruck einen Wert ergab. Ich war sehr daran interessiert, dieses coole Konstrukt wann immer ich konnte zu nutzen. Allerdings war ich naiv und dumm und hätte mehr über die Lesbarkeit von Code nachdenken sollen. Zum Beispiel können Sie folgendes schreiben:

if (a = b)
   fun(a);

Der Wert von b wird in a kopiert und wenn es sich um einen Wert ungleich Null handelt [d.h. TRUE], würde der Funktionsaufruf stattfinden. Alternativ könnte dies auch so geschrieben werden:

a = b;
if (a != 0)
   fun(a);

Dies ist klarer und weniger fehleranfällig. Es ist so einfach, = in einem bedingten Fall zu verwenden, wenn man == verwenden wollte.

Nebenbei bemerkt, denke ich, dass der Code noch klarer wäre, wenn man ihn auf diese Weise schreiben würde:

a = b;
if (a != 0)
{
   fun(a);
}

Der resultierende Binärcode wäre in jedem Fall identisch.

Ein zusätzliches Wort am Ende eines Stapels kann verwendet werden, um einen Überlauf zu überwachen.

Einer der schwierigsten Bugs [sorry, Fehler!], der im Multithreading-Code zu finden ist, ist ein Stapelüberlauf – das Ergebnis, wenn einer Task zu wenig Stack-Speicher zugewiesen wird oder von fehlerhaftem Code. Dies liegt daran, dass der Thread, bei dem das Problem auftritt, tendenziell fortfahren will. Er beschädigt dabei aber den Speicher eines anderen Threads, der dann anfängt sich falsch zu verhalten, obwohl er nicht die Ursache des Problems ist. Natürlich werden Sie Ihren Code gründlich testen und ein solches Problem suchen. Es ist jedoch ratsam, Selbstprüfungscode in die Anwendung aufzunehmen, falls sich das Problem später zeigt. Normalerweise geht es darum, ein „Schutzwort“ direkt hinter dem Ende des Stapels einzufügen. Jede Beschädigung der Inhalte dieses Wortes zeigt an, dass der Stapel übergelaufen ist und ein Problem unmittelbar bevorsteht. Ich habe vor einiger Zeit einen ausführlichen Artikel zu diesem Thema geschrieben. (Beitrag in Englisch).

In C sind Funktionsprototypen nicht obligatorisch. Tun Sie einfach so, als ob sie es wären.

In C++ muss jede Funktion einen Prototyp haben, in C ist das aber nicht zwingend erforderlich. Ich schlage vor, dass Sie so tun, als ob! Dies ist einfach durchzuführen, bietet einige nützliche Dokumentationen und hilft, Fehler zu vermeiden. Ein „normaler“ Prototyp sieht so aus:

unsigned volume(unsigned, unsigned, unsigned);

Sie haben jedoch die Möglichkeit, den Parametern Namen hinzuzufügen:

unsigned volume(unsigned x, unsigned y, unsigned z);

oder sogar

unsigned volume(unsigned width, unsigned height, unsigned depth);

Diese Namen haben ihre Verwendung/Bedeutung an anderer Stelle, können aber sicherlich den Zweck jedes Parameters verdeutlichen.

Fünf weitere Tipps zur Programmierung von Embedded-Software

Fünf weitere Tipps zur Programmierung von Embedded-Software

03.04.18 - Im letzten Teil unserer Software-Tipp-Reihe gab Colin Walls praktische Erfahrungen in der Embedded-Software-Entwicklung weiter, unter anderem zu Null-Pointern oder Rekursivem Code. Hier folgen fünf weitere Hilfestellungen für Embedded-Programmierer. lesen

Fünf Tipps zur Programmierung von Embedded-Software

Fünf Tipps zur Programmierung von Embedded-Software

27.03.18 - Die meisten Softwareentwickler verfügen über eine Art von Ausbildung oder Training, andere sind eher Autodidakten. Aber das wirkliche Lernen in der Programmierung erfolgt durch praktische Erfahrung - und den Austausch von Wissen. Hier sind einige bewährte Tipps, die Autor Colin Walls in langjähriger Erfahrung gesammelt hat. lesen

Colin Walls, Embedded-Software-Technologist bei Mentor, a Siemens business.
Colin Walls, Embedded-Software-Technologist bei Mentor, a Siemens business. (Bild: Caroline Mann)

Der Autor

* Colin Walls verfügt über fast 40 Jahre Erfahrung in der Elektronikindustrie, hauptsächlich im Bereich Embedded Software. Er ist Embedded-Software-Technologist bei Mentor, a Siemens business, mit Sitz in Großbritannien. Walls hält regelmäßig Vorträge auf Konferenzen und Seminaren. Zudem ist er Autor zahlreicher Fachartikel sowie zweier Bücher über Embedded Software und betreibt ein Blog auf http://blogs.mentor.com/colinwalls.

Kommentar zu diesem Artikel abgeben
Es ist Zeit für ein Paar weitere, hoffentlich hilfreiche Tipps für...  lesen
posted am 07.01.2019 um 11:43 von Unregistriert


Mitdiskutieren
copyright

Dieser Beitrag ist urheberrechtlich geschützt. Sie wollen ihn für Ihre Zwecke verwenden? Kontaktieren Sie uns über: support.vogel.de/ (ID: 45672186 / Implementierung)