/* Programm vom 16May22 (T03) */ #include #include /* Mit diesem Makro vermeiden wir es Konstanten zu wiederholen, wie * die Große von einem Array. Deklarieren wir ein Array wie * * int arr[8]; * * dann muss man sich überlegen was `sizeof' in welchen Fällen macht: * * sizeof(arr) = 256 (1) * |______________________________ * / \ * +---+---+---+---+---+---+---+---+ * | 2 | 0 | 4 | 9 | 1 | 1 | 2 | 9 | * +---+---+---+---+---+---+---+---+ * \___/ * | * sizeof(arr[0]) = 32 (2) * * Im Fall (1) bekommen wir den notwendigen Speicher für das ganze * Array (arr), im Fall (2) den notwendigen Speicher für ein einzelnes * Objekt (arr[0], könnte auch jedes beliebige andere sein. Nur ist 0 * wahrscheinlicher Verfügbar als arr[1], arr[2], etc.). * * Um also die Anzahl der Elemente zu bestimmen, brauchen wir nur die * Gleichung * * Gesammtgröße = Elementzahl * Elementgröße * * umstellen, und bekommen * * Elementzahl = Gesammtgröße / Elementgröße * * VORSICHT: Dieses funktioniert bei einem Pointer, dass auf ein Array * verweist NICHT, da sizeof(ptr) (bspw. für ein "char *ptr") immer * einen festen Wert hat, je nachdem wie viel Byte das System * braucht um ein Pointer zu speichern (Auf einem 64 bit system sind * das 8 byte). LEN(*ptr) funktioniert ebenfalls NICHT, da * sizeof(**ptr) bei einem einfachen-Pointer nicht funktioniert. */ #define LEN(a) (sizeof(a)/sizeof(*a)) /* Unsere "Compare" Funktion beschreibt die intuitive Ordnung wo die * Werte hinter jedem Zeiger als integer sortiert werden: */ static int cmp(const void *a, const void *b) { const int *ia = (const int *) a; const int *ib = (const int *) b; /* qsort(3) sagt: * * The comparison function must return an integer less than, * equal to, or greater than zero if THE FIRST ARGUMENT is * considered to be respectively less than, equal to, or * greater than the second. [...] * * Da wir schon mit Zahlen arbeiten, können wir ein paar ifs * vermeiden wenn wir den Arithmetischen unterschied zwischen den * Werten nehmen. Ist *a größer als *b, dann wird auch *a - *b > * 0 sein, etc. * * Es ist natürlich kein Fehler das auszuschreiben, aber Ansätze * wie diesen haben einen theoretischen performance Vorteil * (Stichwort "Branch-less Programming"). */ return *ia - *ib; } int main(void) { int data[12]; /* Es wurden hier die Funktionen srand(3) und rand(3) aus * stdlib.h benutzt um zufällige Zahlen zu generieren. Das * ist weiter nicht wichtig, bis auf die Tatsache das mit * konstantem Seed auch jedes mal unsere Ausgabe gleich sein * wird. */ srand(0); /* seed setzen */ for (size_t i = 0; i < LEN(data); i++) { data[i] = rand() % 1024; } /* Diesen Abschnitt auskommentieren, wenn man sehen will wie * welche Daten vor dem Sortieren wie im Array liegen: */ /* puts("Before:"); */ /* for (int i = 0; i < LEN(data); i++) { */ /* printf("%d\n", data[i]); */ /* } */ /* Zur Wiederholung, die Argumente sind: * * (1) Ein Pointer auf Speicher oder ein Array * (2) Die Anzahl der Elemente im Array * (3) Die Größe jedes einzelnen Elements * (4) Eine Pointer auf eine Callback Funktion, * hier `cmp', mittels welcher wir definieren * Elemente im Array geordnet sind. * * (1) (2) (3) (4) */ qsort(data, LEN(data), sizeof(*data), &cmp); /* Es ist noch notwendig die sortieren Werte auszugeben: */ /* puts("\nAfter:"); */ for (size_t i = 0; i < LEN(data); i++) { printf("%d\n", data[i]); } /* Wenn man sorgfältig sein will, ist es notwendig * sicherzustellen, dass jede Ausgabe auch wirklich ausgegeben * wurde, und nicht im FILE* Buffet verblieben ist. Dieses * ist in SP grundsätzlich notwendig wenn es eine * Kernfunktionalität des Programms ist eine Ausgabe zu * tätigen. * * Mit der Funktion `fflush' können wir das erzwingen, indem * wir dem FILE-Pointer `stdout' dazu zwingen kann diesen zu * leeren. */ if (EOF == fflush(stdout)) { perror("fflush"); exit(EXIT_FAILURE); } /* Ansonsten wird beenden wir unser Prozess mit einem * Erfolgreichen Exit-Code. */ exit(EXIT_SUCCESS); }