|
|
| (3 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) |
| Zeile 10: |
Zeile 10: |
| *[[Makros]] | | *[[Makros]] |
| *[[Kommentare]] | | *[[Kommentare]] |
| == Präfixoperatoren ==
| |
| Präfixoperatoren sind Operatoren, die vor ihren Operanden stehen und verschiedene Arten von Operationen durchführen können. In der C-Programmierung, und somit auch im Kontext des GNU C Compilers (GCC), gibt es mehrere Präfixoperatoren, die eine wichtige Rolle spielen. Hier sind einige der wichtigsten Präfixoperatoren, die in C verwendet werden:
| |
|
| |
|
| === Inkrement (++) und Dekrement (--) ===
| | ----- |
| Inkrement (++): Erhöht den Wert einer Variablen um 1.
| |
| <syntaxhighlight lang="C">
| |
| int a = 5;
| |
| ++a; // a ist jetzt 6
| |
| </syntaxhighlight>
| |
| Dekrement (--): Verringert den Wert einer Variablen um 1.
| |
| <syntaxhighlight lang="C">
| |
| int b = 5;
| |
| --b; // b ist jetzt 4 | |
| </syntaxhighlight>
| |
| === Dereferenzierungsoperator (*) ===
| |
| Dereferenzierungsoperator (*): Wird verwendet, um auf den Wert zuzugreifen, auf den ein Zeiger zeigt.
| |
| <syntaxhighlight lang="C">
| |
| int x = 10;
| |
| int *ptr = &x;
| |
| int y = *ptr; // y ist jetzt 10
| |
| </syntaxhighlight>
| |
| === Adressoperator (&) ===
| |
| Adressoperator (&): Gibt die Adresse einer Variablen zurück.
| |
| <syntaxhighlight lang="C">
| |
| int z = 20;
| |
| int *ptr = &z; // ptr enthält die Adresse von z
| |
| </syntaxhighlight>
| |
| === Logisches Nicht (!) ===
| |
| Logisches Nicht (!): Negiert einen logischen Wert. Wenn der Operand wahr ist, wird er falsch und umgekehrt.
| |
| <syntaxhighlight lang="C">
| |
| int flag = 0;
| |
| if (!flag) {
| |
| // Dieser Block wird ausgeführt, da !0 wahr ist
| |
| }
| |
| </syntaxhighlight>
| |
| === Bitweises Nicht (~) ===
| |
| Bitweises Nicht (~): Invertiert alle Bits eines Wertes.
| |
| <syntaxhighlight lang="C">
| |
| unsigned int num = 0b1010; // Binär: 1010
| |
| unsigned int result = ~num; // Binär: 0101 (in 4-Bit-Darstellung)
| |
| </syntaxhighlight>
| |
| === Vorzeichenwechsel (-) ===
| |
| Vorzeichenwechsel (-): Ändert das Vorzeichen eines Wertes.
| |
| <syntaxhighlight lang="C">
| |
| int positive = 5;
| |
| int negative = -positive; // negative ist jetzt -5
| |
| </syntaxhighlight>
| |
| === Größe des Operators (sizeof) ===
| |
| Größe des Operators (sizeof): Gibt die Größe eines Datentyps oder einer Variable in Bytes zurück.
| |
| <syntaxhighlight lang="C">
| |
| int a = 5;
| |
| size_t size = sizeof(a); // size ist die Anzahl der Bytes, die ein int belegt
| |
| </syntaxhighlight>
| |
| === Beispiel für die Verwendung von Präfixoperatoren ===
| |
| Hier ist ein einfaches Beispiel, das verschiedene Präfixoperatoren kombiniert:
| |
| <syntaxhighlight lang="C">
| |
| #include <stdio.h>
| |
|
| |
|
| int main() {
| | {| style="width: 100%; |
| int a = 5;
| | | style="width: 33%;" | [[GNU Assembler|< Zurück (GNU Assembler)]] |
| int b = 10;
| | | style="width: 33%; text-align:center;" | [[Hauptseite|< Hauptseite >]] |
| int *ptr = &a;
| | | style="width: 33%; text-align:right;" | [[Geschichte und Entwicklung|Weiter (Geschichte und Entwicklung) >]] |
| | | |} |
| // Inkrement und Dekrement
| |
| ++a; // a ist jetzt 6
| |
| --b; // b ist jetzt 9
| |
| | |
| // Dereferenzierungs- und Adressoperator
| |
| int c = *ptr; // c ist jetzt 6 (Wert von a)
| |
| int *ptr_b = &b;
| |
| | |
| // Logisches Nicht
| |
| int flag = 0;
| |
| if (!flag) {
| |
| printf("Flag ist falsch\n");
| |
| }
| |
| | |
| // Bitweises Nicht
| |
| unsigned int num = 0b1010;
| |
| unsigned int result = ~num;
| |
| | |
| // Vorzeichenwechsel
| |
| int positive = 5;
| |
| int negative = -positive;
| |
| | |
| // Größe des Operators
| |
| size_t size_of_int = sizeof(int);
| |
| | |
| // Ausgabe der Ergebnisse
| |
| printf("a: %d, b: %d, c: %d\n", a, b, c);
| |
| printf("result (bitweises Nicht): %u\n", result);
| |
| printf("negative: %d\n", negative);
| |
| printf("Größe eines int: %zu Bytes\n", size_of_int);
| |
| | |
| return 0;
| |
| }
| |
| </syntaxhighlight>
| |
| Dieses Beispiel zeigt die Verwendung der verschiedenen Präfixoperatoren und wie sie in einem einfachen Programm verwendet werden können.
| |
| | |
| == 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.
| |
| <syntaxhighlight lang="C">
| |
| int sum = a + b;
| |
| </syntaxhighlight>
| |
| Subtraktion (-): Subtrahiert den zweiten Operanden vom ersten.
| |
| <syntaxhighlight lang="C">
| |
| int difference = a - b;
| |
| </syntaxhighlight>
| |
| Multiplikation (*): Multipliziert zwei Operanden.
| |
| <syntaxhighlight lang="C">
| |
| int product = a * b;
| |
| </syntaxhighlight>
| |
| Division (/): Teilt den ersten Operanden durch den zweiten.
| |
| <syntaxhighlight lang="C">
| |
| int quotient = a / b;
| |
| </syntaxhighlight>
| |
| Modulus (%): Gibt den Rest der Division des ersten Operanden durch den zweiten zurück.
| |
| <syntaxhighlight lang="C">
| |
| int remainder = a % b;
| |
| </syntaxhighlight>
| |
| | |
| === Vergleichsoperatoren ===
| |
| Gleich (==): Überprüft, ob zwei Operanden gleich sind.
| |
| <syntaxhighlight lang="C">
| |
| if (a == b) { /* ... */ }
| |
| </syntaxhighlight>
| |
| Ungleich (!=): Überprüft, ob zwei Operanden ungleich sind.
| |
| <syntaxhighlight lang="C">
| |
| if (a != b) { /* ... */ }
| |
| </syntaxhighlight>
| |
| Größer als (>): Überprüft, ob der erste Operand größer als der zweite ist.
| |
| <syntaxhighlight lang="C">
| |
| if (a > b) { /* ... */ }
| |
| </syntaxhighlight>
| |
| Kleiner als (<): Überprüft, ob der erste Operand kleiner als der zweite ist.
| |
| <syntaxhighlight lang="C">
| |
| if (a < b) { /* ... */ }
| |
| </syntaxhighlight>
| |
| Größer oder gleich (>=): Überprüft, ob der erste Operand größer oder gleich dem zweiten ist.
| |
| <syntaxhighlight lang="C">
| |
| if (a >= b) { /* ... */ }
| |
| </syntaxhighlight>
| |
| Kleiner oder gleich (<=): Überprüft, ob der erste Operand kleiner oder gleich dem zweiten ist.
| |
| <syntaxhighlight lang="C">
| |
| if (a <= b) { /* ... */ }
| |
| </syntaxhighlight>
| |
| === Logische Operatoren ===
| |
| Logisches UND (&&): Gibt wahr zurück, wenn beide Operanden wahr sind.
| |
| <syntaxhighlight lang="C">
| |
| if (a && b) { /* ... */ }
| |
| </syntaxhighlight>
| |
| Logisches ODER (||): Gibt wahr zurück, wenn mindestens einer der Operanden wahr ist.
| |
| <syntaxhighlight lang="C"> | |
| if (a || b) { /* ... */ }
| |
| </syntaxhighlight>
| |
| === Bitweise Operatoren ===
| |
| Bitweises UND (&): Führt ein bitweises UND zwischen zwei Operanden durch.
| |
| <syntaxhighlight lang="C">
| |
| int result = a & b;
| |
| </syntaxhighlight>
| |
| Bitweises ODER (|): Führt ein bitweises ODER zwischen zwei Operanden durch.
| |
| <syntaxhighlight lang="C">
| |
| int result = a | b;
| |
| </syntaxhighlight>
| |
| Bitweises XOR (^): Führt ein bitweises exklusives ODER zwischen zwei Operanden durch.
| |
| <syntaxhighlight lang="C">
| |
| int result = a ^ b;
| |
| </syntaxhighlight>
| |
| Linksschiebung (<<): Verschiebt die Bits des ersten Operanden um die Anzahl der im zweiten Operanden angegebenen Bits nach links.
| |
| <syntaxhighlight lang="C">
| |
| int result = a << 1;
| |
| </syntaxhighlight>
| |
| Rechtsschiebung (>>): Verschiebt die Bits des ersten Operanden um die Anzahl der im zweiten Operanden angegebenen Bits nach rechts.
| |
| <syntaxhighlight lang="C">
| |
| int result = a >> 1;
| |
| </syntaxhighlight>
| |
| | |
| === Zuweisungsoperatoren ===
| |
| Zuweisung (=): Weist den Wert des rechten Operanden dem linken Operanden zu.
| |
| <syntaxhighlight lang="C">
| |
| a = b;
| |
| </syntaxhighlight>
| |
| Kombinierte Zuweisungsoperatoren: Diese Operatoren kombinieren eine Operation mit einer Zuweisung.
| |
| <syntaxhighlight lang="C">
| |
| 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;
| |
| </syntaxhighlight>
| |
| === Beispiel für die Verwendung von Infix-Operatoren ===
| |
| | |
| Hier ist ein einfaches Beispiel, das verschiedene Infix-Operatoren kombiniert:
| |
| | |
| <syntaxhighlight lang="C">
| |
| #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;
| |
| }
| |
| </syntaxhighlight>
| |
| 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">
| |
| #if defined(DEBUG)
| |
| // Code wird nur kompiliert, wenn DEBUG definiert ist
| |
| printf("Debug mode\n");
| |
| #else
| |
| // Alternativer Code wird kompiliert, wenn DEBUG nicht definiert ist
| |
| printf("Production mode\n");
| |
| #endif
| |
| <\syntaxhighlight>
| |
| '''#ifdef''' und '''#ifndef''': Diese Direktiven prüfen, ob ein Symbol definiert ist oder nicht.
| |
| <syntaxhighlight lang="C">
| |
| #ifdef DEBUG
| |
| // Dieser Code wird kompiliert, wenn DEBUG definiert ist
| |
| printf("Debug mode\n");
| |
| #endif
| |
| | |
| #ifndef RELEASE
| |
| // Dieser Code wird kompiliert, wenn RELEASE nicht definiert ist
| |
| printf("Not in release mode\n");
| |
| #endif
| |
| <\syntaxhighlight>
| |
| '''#elif''': Diese Direktive ermöglicht zusätzliche Bedingungen innerhalb einer #if-Kette.
| |
| <syntaxhighlight lang="C">
| |
| #if LEVEL == 1
| |
| printf("Level 1\n");
| |
| #elif LEVEL == 2
| |
| printf("Level 2\n");
| |
| #else
| |
| printf("Other level\n");
| |
| #endif
| |
| <\syntaxhighlight>
| |
| '''#define''' und '''#undef''': Verwenden Sie diese Direktiven, um Symbole zu definieren oder deren Definition aufzuheben.
| |
| <syntaxhighlight lang="C">
| |
| #define FEATURE_X
| |
| #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">
| |
| #include <stdio.h>
| |
| | |
| #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">
| |
| #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">
| |
| #include <stdio.h>
| |
| | |
| #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">
| |
| #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>
| |