GNU C Compiler

Aus C und Assembler mit Raspberry

Der GNU C Compiler, häufig als GCC (GNU Compiler Collection) bezeichnet, ist ein weit verbreiteter Compiler, der ursprünglich für die Programmiersprache C entwickelt wurde. Heute unterstützt GCC eine Vielzahl von Programmiersprachen und Prozessorarchitekturen. Hier sind einige wichtige Punkte über den GNU C Compiler:

Infix-Operatoren

Infix-Operatoren sind Operatoren, die zwischen ihren Operanden stehen und eine Vielzahl von Operationen durchführen können. In der C-Programmierung, und somit im Kontext des GNU C Compilers (GCC), gibt es zahlreiche Infix-Operatoren, die in verschiedene Kategorien unterteilt werden können, wie z.B. arithmetische, logische, bitweise und Vergleichsoperatoren. Hier sind einige der wichtigsten Infix-Operatoren, die in C verwendet werden:

Arithmetische Operatoren

Addition (+): Fügt zwei Operanden zusammen.

int sum = a + b;

Subtraktion (-): Subtrahiert den zweiten Operanden vom ersten.

int difference = a - b;

Multiplikation (*): Multipliziert zwei Operanden.

int product = a * b;

Division (/): Teilt den ersten Operanden durch den zweiten.

int quotient = a / b;

Modulus (%): Gibt den Rest der Division des ersten Operanden durch den zweiten zurück.

int remainder = a % b;

Vergleichsoperatoren

Gleich (==): Überprüft, ob zwei Operanden gleich sind.

if (a == b) { /* ... */ }

Ungleich (!=): Überprüft, ob zwei Operanden ungleich sind.

if (a != b) { /* ... */ }

Größer als (>): Überprüft, ob der erste Operand größer als der zweite ist.

if (a > b) { /* ... */ }

Kleiner als (<): Überprüft, ob der erste Operand kleiner als der zweite ist.

if (a < b) { /* ... */ }

Größer oder gleich (>=): Überprüft, ob der erste Operand größer oder gleich dem zweiten ist.

if (a &gt;= b) { /* ... */ }

Kleiner oder gleich (<=): Überprüft, ob der erste Operand kleiner oder gleich dem zweiten ist.

if (a &lt;= b) { /* ... */ }

Logische Operatoren

Logisches UND (&&): Gibt wahr zurück, wenn beide Operanden wahr sind.

if (a && b) { /* ... */ }

Logisches ODER (||): Gibt wahr zurück, wenn mindestens einer der Operanden wahr ist.

if (a || b) { /* ... */ }

Bitweise Operatoren

Bitweises UND (&): Führt ein bitweises UND zwischen zwei Operanden durch.

int result = a & b;

Bitweises ODER (|): Führt ein bitweises ODER zwischen zwei Operanden durch.

int result = a | b;

Bitweises XOR (^): Führt ein bitweises exklusives ODER zwischen zwei Operanden durch.

int result = a ^ b;

Linksschiebung (<<): Verschiebt die Bits des ersten Operanden um die Anzahl der im zweiten Operanden angegebenen Bits nach links.

int result = a << 1;

Rechtsschiebung (>>): Verschiebt die Bits des ersten Operanden um die Anzahl der im zweiten Operanden angegebenen Bits nach rechts.

int result = a >> 1;

Zuweisungsoperatoren

Zuweisung (=): Weist den Wert des rechten Operanden dem linken Operanden zu.

a = b;

Kombinierte Zuweisungsoperatoren: Diese Operatoren kombinieren eine Operation mit einer Zuweisung.

a += b;  // Entspricht a = a + b;
a -= b;  // Entspricht a = a - b;
a *= b;  // Entspricht a = a * b;
a /= b;  // Entspricht a = a / b;
a %= b;  // Entspricht a = a % b;
a &= b;  // Entspricht a = a & b;
a |= b;  // Entspricht a = a | b;
a ^= b;  // Entspricht a = a ^ b;
a <<= b; // Entspricht a = a << b;
a >>= b; // Entspricht a = a >> b;

Beispiel für die Verwendung von Infix-Operatoren

Hier ist ein einfaches Beispiel, das verschiedene Infix-Operatoren kombiniert:

#include <stdio.h>

int main() {
    int a = 10;
    int b = 5;
    int sum = a + b;
    int difference = a - b;
    int product = a * b;
    int quotient = a / b;
    int remainder = a % b;

    int isEqual = (a == b);
    int isNotEqual = (a != b);
    int isGreater = (a > b);
    int isLess = (a < b);
    int isGreaterOrEqual = (a >= b);
    int isLessOrEqual = (a <= b);

    int logicalAnd = (a && b);
    int logicalOr = (a || b);

    int bitwiseAnd = a & b;
    int bitwiseOr = a | b;
    int bitwiseXor = a ^ b;
    int leftShift = a << 1;
    int rightShift = a >> 1;

    printf("Sum: %d\n", sum);
    printf("Difference: %d\n", difference);
    printf("Product: %d\n", product);
    printf("Quotient: %d\n", quotient);
    printf("Remainder: %d\n", remainder);

    printf("Is Equal: %d\n", isEqual);
    printf("Is Not Equal: %d\n", isNotEqual);
    printf("Is Greater: %d\n", isGreater);
    printf("Is Less: %d\n", isLess);
    printf("Is Greater Or Equal: %d\n", isGreaterOrEqual);
    printf("Is Less Or Equal: %d\n", isLessOrEqual);

    printf("Logical AND: %d\n", logicalAnd);
    printf("Logical OR: %d\n", logicalOr);

    printf("Bitwise AND: %d\n", bitwiseAnd);
    printf("Bitwise OR: %d\n", bitwiseOr);
    printf("Bitwise XOR: %d\n", bitwiseXor);
    printf("Left Shift: %d\n", leftShift);
    printf("Right Shift: %d\n", rightShift);

    return 0;
}

Dieses Beispiel zeigt die Verwendung verschiedener Infix-Operatoren und wie sie in einem einfachen Programm verwendet werden können.

Bedingte Kompilierung

Bedingte Kompilierung mit dem GCC-Compiler (GNU Compiler Collection) ist eine Technik, die es ermöglicht, bestimmte Teile des Codes abhängig von definierten Bedingungen zu kompilieren oder auszulassen. Dies ist besonders nützlich, um plattform- oder konfigurationsspezifischen Code zu schreiben und zu verwalten, Debugging zu aktivieren oder zu deaktivieren, oder experimentelle Funktionen einzuschließen.

Hier sind die wichtigsten Aspekte der bedingten Kompilierung im Zusammenhang mit GCC:

Präprozessor-Direktiven für Bedingte Kompilierung

#if,#else und #endif: Diese Präprozessor-Direktiven werden verwendet, um Codeblöcke basierend auf Bedingungen ein- oder auszuschließen.

<syntaxhighlight lang="C">

  1. if defined(DEBUG)
   // Code wird nur kompiliert, wenn DEBUG definiert ist
   printf("Debug mode\n");
  1. else
   // Alternativer Code wird kompiliert, wenn DEBUG nicht definiert ist
   printf("Production mode\n");
  1. endif

<\syntaxhighlight> #ifdef und #ifndef: Diese Direktiven prüfen, ob ein Symbol definiert ist oder nicht. <syntaxhighlight lang="C">

  1. ifdef DEBUG
   // Dieser Code wird kompiliert, wenn DEBUG definiert ist
   printf("Debug mode\n");
  1. endif
  1. ifndef RELEASE
   // Dieser Code wird kompiliert, wenn RELEASE nicht definiert ist
   printf("Not in release mode\n");
  1. endif

<\syntaxhighlight> #elif: Diese Direktive ermöglicht zusätzliche Bedingungen innerhalb einer #if-Kette. <syntaxhighlight lang="C">

  1. if LEVEL == 1
   printf("Level 1\n");
  1. elif LEVEL == 2
   printf("Level 2\n");
  1. else
   printf("Other level\n");
  1. endif

<\syntaxhighlight> #define und #undef: Verwenden Sie diese Direktiven, um Symbole zu definieren oder deren Definition aufzuheben. <syntaxhighlight lang="C">

  1. define FEATURE_X
  2. undef FEATURE_X

<\syntaxhighlight>

Praktische Anwendungen

Debugging und Entwicklungsmodi

Bedingte Kompilierung ist besonders nützlich, um Debugging-Funktionalitäten ein- oder auszuschalten: <syntaxhighlight lang="C">

  1. include <stdio.h>
  1. define DEBUG

int main() {

   int val = 42;
   #ifdef DEBUG
       printf("Debug: val = %d\n", val);
   #else
       printf("Release: val = %d\n", val);
   #endif
   return 0;

} <\syntaxhighlight> Wenn das Symbol DEBUG definiert ist, wird die Debugging-Ausgabe aktiviert. Andernfalls wird die Release-Ausgabe verwendet.

Plattformübergreifende Kompilierung

Bedingte Kompilierung kann verwendet werden, um spezifischen Code für verschiedene Betriebssysteme oder Architekturen zu schreiben: <syntaxhighlight lang="C">

  1. include <stdio.h>

int main() {

   #ifdef _WIN32
       printf("Running on Windows\n");
   #elif __linux__
       printf("Running on Linux\n");
   #elif __APPLE__
       printf("Running on macOS\n");
   #else
       printf("Unknown Platform\n");
   #endif
   return 0;

} <\syntaxhighlight> Hier wird basierend auf dem Zielbetriebssystem unterschiedlicher Code kompiliert.

Feature-Toggles

Mit bedingter Kompilierung können Funktionen basierend auf definierten Symbolen aktiviert oder deaktiviert werden: <syntaxhighlight lang="C">

  1. include <stdio.h>
  1. define FEATURE_X

int main() {

   #ifdef FEATURE_X
       printf("Feature X is enabled\n");
   #else
       printf("Feature X is disabled\n");
   #endif
   return 0;

} <\syntaxhighlight> Je nachdem, ob FEATURE_X definiert ist oder nicht, wird der entsprechende Code kompiliert.

Kompilierungsflags mit GCC

Symbole können direkt beim Aufruf des Compilers definiert oder entfernt werden, was die Flexibilität erhöht: <syntaxhighlight lang="Shell"> gcc -DDEBUG -o myprogram myprogram.c <\syntaxhighlight> Hier definiert -DDEBUG das Symbol DEBUG während der Kompilierung.

Beispiel für Kompilierung mit GCC

Angenommen, wir haben den folgenden C-Code: <syntaxhighlight lang="C">

  1. include <stdio.h>

int main() {

   #ifdef DEBUG
       printf("Debug mode enabled\n");
   #else
       printf("Production mode\n");
   #endif
   return 0;

} <\syntaxhighlight> Wir können den Code mit und ohne Debugging-Informationen kompilieren:

Mit Debugging: <syntaxhighlight lang="Shell"> gcc -DDEBUG -o myprogram myprogram.c ./myprogram # Ausgabe: Debug mode enabled <\syntaxhighlight> Ohne Debugging: <syntaxhighlight lang="Shell"> gcc -o myprogram myprogram.c ./myprogram # Ausgabe: Production mode <\syntaxhighlight>