Nah an der Hardware: schnell, klein, die Grundlage vieler Systeme
Ausführen: Datei hallo.c speichern, mit gcc -Wall -Wextra -std=c17 hallo.c -o hallo übersetzen und mit ./hallo starten (Windows: hallo.exe). Auf Linux und macOS ist gcc oder clang meist vorhanden, unter Windows hilft MinGW oder WSL.
-Wall -Wextra übersetzenint main(void); return 0 heißt Erfolggcc -Wall -Wextra -std=c17 -o hallo hallo.c
./hallo#include, Prototypen, main, Funktionsdefinitionenprintf mit Platzhaltern (%d, %f, %s, %c); sie müssen zum Typ passen-Wall -Wextra immer einschalten, Warnungen behebenmain meldet Erfolg (0) oder Fehler#include <stdio.h> /* Präprozessor: Header einbinden */
#define MAX 3 /* Makro: wird vor dem Übersetzen ersetzt */
// Funktionsprototyp (Deklaration)
int quadrat(int x);
int main(void) {
for (int i = 1; i <= MAX; i++) {
printf("%d zum Quadrat ist %d\n", i, quadrat(i));
}
return 0;
}
// Funktionsdefinition
int quadrat(int x) {
return x * x;
}char, int, long long, float, double, bool, unsigned; feste Größen aus <stdint.h>sizeof liefert die Größe in Bytes7 / 2.0 rechnet als Kommazahlconst statt Magic Numbersstatic lokal behält den Wert zwischen Aufrufen#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
int main(void) {
int alter = 17;
unsigned int zaehler = 3000000000u;
long long gross = 9000000000LL;
double pi = 3.14159265358979;
char buchstabe = 'A';
bool fertig = true;
uint8_t byte = 255;
printf("%d %u %lld %.5f %c %d %d\n", alter, zaehler, gross, pi, buchstabe, fertig, byte);
printf("Größen: char %zu, short %zu, int %zu, long %zu, long long %zu, double %zu, Zeiger %zu\n",
sizeof(char), sizeof(short), sizeof(int), sizeof(long), sizeof(long long), sizeof(double), sizeof(void *));
printf("INT_MAX = %d, INT_MIN = %d\n", INT_MAX, INT_MIN);
return 0;
}= ist Zuweisung, == Vergleich; Compiler-Warnungen aktivieren&, |, ^, ~, <<, >> für Flags und Masken#include <stdio.h>
int main(void) {
int a = 17, b = 5;
printf("%d %d %d %d %d\n", a + b, a - b, a * b, a / b, a % b);
printf("%d %d %d\n", a > b, a == b, !(a > b));
printf("%d %d\n", a > 10 && b < 3, a > 10 || b < 3);
int i = 5;
int alt = i++; // erst benutzen, dann erhöhen
int neu = ++i; // erst erhöhen, dann benutzen
printf("%d %d %d\n", alt, neu, i);
int x = 10;
x += 5; x *= 2; x -= 1; x /= 3; x %= 7;
printf("%d\n", x);
printf("%d\n", a > b ? a : b);
return 0;
}printf, puts, fprintf(stderr, ...); Pufferausgabe mit snprintffgets lesen, dann mit sscanf/strtol/strtod auswertenscanf immer prüfen; bei %s Breite angebengets benutzenEOF ist ein int: Variable mit int deklarieren#include <stdio.h>
int main(void) {
puts("Hallo");
putchar('X'); putchar('\n');
fprintf(stderr, "Das geht an stderr\n");
char puffer[50];
int n = snprintf(puffer, sizeof puffer, "%s hat %d Punkte (%.1f%%)", "Mia", 42, 87.5);
printf("%s [%d Zeichen]\n", puffer, n);
return 0;
}{ } setzenswitch für Ganzzahlen, break nicht vergessenfor für Zählschleifen, while für Bedingungen, do-while läuft mindestens einmalbreak beendet, continue überspringt; goto nur selten; hinter der Schleife ist ein klassischer Fehler#include <stdio.h>
int main(void) {
int punkte = 73;
if (punkte >= 90) {
puts("sehr gut");
} else if (punkte >= 75) {
puts("gut");
} else if (punkte >= 50) {
puts("bestanden");
} else {
puts("nicht bestanden");
}
int x = 0;
if (x) puts("wahr"); else puts("falsch (0 ist falsch)");
const char *text = "";
if (text && text[0]) puts("nicht leer"); else puts("leer");
return 0;
}Rückgabetyp name(Parameter); void für "nichts"&x, *p)structqsort)static bei Funktionen macht sie dateilokal#include <stdio.h>
int addiere(int a, int b) {
return a + b;
}
void gruss(const char *name) {
printf("Hallo %s!\n", name);
}
double mittelwert(double a, double b) { return (a + b) / 2; }
int main(void) {
printf("%d\n", addiere(3, 4));
gruss("Mia");
printf("%.1f\n", mittelwert(3, 4));
return 0;
}char-Array mit abschließendem '\0'strcmp vergleichen, mit snprintf sicher zusammensetzenstrcpy/strcat/gets können Puffer überlaufen lassenstrtol/strtod statt atoi/atof#include <stdio.h>
int main(void) {
int z[5] = {10, 20, 30}; // Rest wird 0
int auto_groesse[] = {1, 2, 3, 4}; // Größe 4 erkannt
int n = sizeof auto_groesse / sizeof auto_groesse[0];
printf("%d %d %d %d\n", z[0], z[2], z[4], n);
z[1] = 99;
for (int i = 0; i < 5; i++) printf("%d ", z[i]);
printf("\n");
int matrix[2][3] = { {1, 2, 3}, {4, 5, 6} };
printf("%d %zu %zu\n", matrix[1][2], sizeof matrix / sizeof matrix[0], sizeof matrix[0] / sizeof matrix[0][0]);
return 0;
}&x holt sie, *p greift darauf zuNULL heißt "nichts"; vor Zugriff prüfenp[i] ist *(p + i)const int *p schützt die Daten; void * ist ein typloser Zeiger#include <stdio.h>
int main(void) {
int zahl = 42;
int *p = &zahl; // p speichert die Adresse von zahl
printf("Wert: %d, Zeiger zeigt auf: %d\n", zahl, *p);
*p = 100; // Wert über den Zeiger ändern
printf("zahl ist jetzt %d\n", zahl);
printf("gleiche Adresse: %d\n", p == &zahl);
printf("Größe des Zeigers: %zu Byte\n", sizeof p);
return 0;
}struct bündelt Felder; Zugriff mit . bzw. -> bei Zeigerntypedef gibt Typen kürzere Namen; Strukturen lassen sich kopieren und per Zeiger übergebenenum für benannte Ganzzahl-Konstanten; union teilt sich einen Speicherplatz#include <stdio.h>
#include <string.h>
struct Person {
char name[32];
int alter;
double gewicht;
};
int main(void) {
struct Person mia = { "Mia", 17, 58.5 };
struct Person tom = { .name = "Tom", .alter = 19 }; // benannte Initialisierung, Rest = 0
mia.alter++;
strcpy(tom.name, "Tom K.");
printf("%s %d %.1f\n", mia.name, mia.alter, mia.gewicht);
printf("%s %d %.1f\n", tom.name, tom.alter, tom.gewicht);
struct Person kopie = mia; // Struktur komplett kopieren
kopie.alter = 99;
printf("%d %d\n", mia.alter, kopie.alter);
printf("Größe: %zu\n", sizeof(struct Person));
return 0;
}malloc/freemalloc prüfen, sizeof *p verwenden, jeden Block genau einmal freigebenrealloc in eine Hilfsvariable; Zeiger nach free auf NULL#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n = 5;
int *a = malloc(n * sizeof *a); // n ints, nicht initialisiert
if (a == NULL) { fprintf(stderr, "kein Speicher\n"); return 1; }
for (int i = 0; i < n; i++) a[i] = i * i;
int *b = calloc(n, sizeof *b); // n ints, alle 0
printf("%d %d %d\n", a[4], b[0], b[4]);
int *c = realloc(a, 10 * sizeof *a); // Größe ändern (kann verschieben!)
if (c == NULL) { free(a); free(b); return 1; }
a = c;
a[9] = 81;
printf("%d %d\n", a[4], a[9]);
free(a); // jeden reservierten Block freigeben
free(b);
return 0;
}fopen liefert NULL bei Fehlern: immer prüfen; fclose nicht vergessenfprintf, fgets, fscanf; Binärdaten: fwrite, fread mit Modus "rb"/"wb"fgets und Puffergrößeperror zeigt den Grund eines Fehlers#include <stdio.h>
#include <string.h>
int main(void) {
const char *pfad = "notiz.txt";
FILE *f = fopen(pfad, "w");
if (f == NULL) { perror("fopen"); return 1; }
fprintf(f, "Zeile %d\n", 1);
fputs("Zeile 2\n", f);
fclose(f);
f = fopen(pfad, "a"); // anhängen
if (f) { fputs("Zeile 3\n", f); fclose(f); }
f = fopen(pfad, "r");
if (f == NULL) { perror("fopen"); return 1; }
char zeile[64];
int nr = 0;
while (fgets(zeile, sizeof zeile, f) != NULL) { // zeilenweise lesen
zeile[strcspn(zeile, "\n")] = '\0';
printf("%d: %s\n", ++nr, zeile);
}
fclose(f);
FILE *fehlt = fopen("gibt-es-nicht.txt", "r");
if (!fehlt) perror("Fehler"); // gibt eine lesbare Meldung aus
remove(pfad);
return 0;
}#include, #define, #ifdef) vor dem Compiler.h) enthalten die Schnittstelle, .c-Dateien die Umsetzungstatic inline und constmake oder CMake bauen größere Projekte automatisch#include <stdio.h>
#define PI 3.14159
#define QUADRAT(x) ((x) * (x)) // alle Klammern setzen!
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define VERSION "1.2"
#ifdef DEBUG
#define LOG(msg) printf("[DEBUG] %s\n", msg)
#else
#define LOG(msg) ((void) 0)
#endif
int main(void) {
printf("%.2f %d %d\n", PI * QUADRAT(2), QUADRAT(3 + 1), MAX(4, 9));
printf("Version %s, Datei %s, Zeile %d\n", VERSION, "x.c", __LINE__);
LOG("nur mit -DDEBUG sichtbar");
#if defined(__linux__)
puts("Linux");
#elif defined(_WIN32)
puts("Windows");
#else
puts("anderes System");
#endif
return 0;
}-Wall -Wextra, Sanitizer, Valgrind und statische Analyse finden die meisten Fehler früh#include <stdio.h>
#include <limits.h>
#include <stdbool.h>
bool addiere_sicher(int a, int b, int *ergebnis) {
if ((b > 0 && a > INT_MAX - b) || (b < 0 && a < INT_MIN - b)) return false;
*ergebnis = a + b;
return true;
}
int main(void) {
int r;
printf("%d\n", addiere_sicher(2000000000, 100000000, &r)); // passt
printf("%d\n", addiere_sicher(2000000000, 200000000, &r)); // Überlauf
printf("%d\n", __builtin_add_overflow(INT_MAX, 1, &r)); // GCC/Clang: eingebaute Prüfung
return 0;
}#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define LEN(a) (sizeof (a) / sizeof (a)[0])
typedef struct { int id; char name[16]; } Eintrag;
static int nach_id(const void *a, const void *b) {
return ((const Eintrag *) a)->id - ((const Eintrag *) b)->id;
}
int main(void) {
// Array-Länge
int z[] = {4, 8, 15, 16, 23, 42};
printf("%zu\n", LEN(z));
// Sortieren und binär suchen
Eintrag e[] = { {3, "c"}, {1, "a"}, {2, "b"} };
qsort(e, LEN(e), sizeof e[0], nach_id);
Eintrag such = { 2, "" };
Eintrag *treffer = bsearch(&such, e, LEN(e), sizeof e[0], nach_id);
printf("%s\n", treffer ? treffer->name : "nicht gefunden");
// Zufallszahl 1..6
srand((unsigned) time(NULL));
int w = rand() % 6 + 1;
printf("%d\n", w >= 1 && w <= 6);
// String umkehren
char s[] = "Hallo";
for (size_t i = 0, j = strlen(s) - 1; i < j; i++, j--) { char t = s[i]; s[i] = s[j]; s[j] = t; }
printf("%s\n", s);
return 0;
}