Collections-C ist eine Bibliothek generischer Datenstrukturen für die C-Sprache.
Strukturen, die Daten in der Form void*
speichern.
Container | Beschreibung |
---|---|
CC_Array | Ein dynamisches Array, das automatisch erweitert wird, wenn Elemente hinzugefügt werden. |
CC_List | Doppelt verknüpfte Liste. |
CC_SList | Einfach verknüpfte Liste. |
CC_Deque | Ein dynamisches Array, das das amortisierte Einfügen und Entfernen mit konstanter Zeit an beiden Enden und den Zugriff mit konstanter Zeit unterstützt. |
CC_HashTable | Eine ungeordnete Schlüsselwertzuordnung. Unterstützt im besten Fall das Einfügen, Entfernen und Nachschlagen von Werten mit amortisierter konstanter Zeit. |
CC_TreeTable | Eine geordnete Schlüssel-Wert-Karte. Unterstützt logarithmisches Einfügen, Entfernen und Suchen von Werten. |
CC_HashSet | Eine ungeordnete Menge. Das Suchen, Löschen und Einfügen erfolgt in amortisierter konstanter Zeit und im schlimmsten Fall in amortisierter linearer Zeit. |
CC_TreeSet | Ein geordnetes Set. Das Suchen, Löschen und Einfügen erfolgt in logarithmischer Zeit. |
CC_Queue | Eine FIFO-Struktur (First In First Out). Unterstützt konstantes Einfügen, Entfernen und Suchen. |
CC_Stack | Eine LIFO-Struktur (Last In First Out). Unterstützt konstantes Einfügen, Entfernen und Suchen. |
CC_PQueue | Eine Prioritätswarteschlange. |
CC_RingBuffer | Ein Ringpuffer. |
CC_TSTTable | Eine ternäre Suchbaumtabelle. Unterstützt Einfügen, Suchen, Iteration und Löschen. |
int value = 20 ;
CC_Array * array ;
if ( cc_array_new ( & array ) != CC_OK ) { /*Create a new array.*/
// handle error
}
if ( cc_array_add ( & array , ( void * ) & value ) != CC_OK ) { /* Add the pointer to the value to the array */
// handle error
}
Strukturen, die Daten beliebiger Länge direkt speichern.
Container | Beschreibung |
---|---|
CC_ArraySized | Ein dynamisches Array, das automatisch erweitert wird, wenn Elemente hinzugefügt werden. |
int value = 20 ;
CC_SizedArray * array ;
if ( cc_sized_array_new ( sizeof ( int ), & array ) != CC_OK ) { /* Create a new array that stores values the size of an int*/
// handle error
}
if ( cc_sized_array_add ( & array , & value ) != CC_OK ) { /* Copy the value into the array */
// handle error
}
Speicherpools sind vorab zugewiesene Blöcke zusammenhängenden Speichers
Container | Beschreibung |
---|---|
CC_DynamicPool | Auf dem Heap potenziell erweiterbarer Speicherpool |
CC_StaticPool | Fester Pool |
/* CC_StaticPool can enable the use of the structures on the stack */
#include "memory/cc_static_pool.h"
#include "cc_list.h"
CC_StaticPool * pool ;
// Alloc wrappers
void * pool_malloc ( size_t size ) { cc_static_pool_malloc ( size , pool );}
void * pool_calloc ( size_t count , size_t size ) { cc_static_pool_calloc ( count , size , pool );}
void pool_free ( void * ptr ) { cc_static_pool_free ( ptr , pool );}
int main ( int argc , char * * argv ) {
uint8_t buffer [ 2000 ]; /* Large enough buffer. */
cc_static_pool_new ( sizeof ( buffer ), 0 , buffer , buffer , & pool ); /* allocate the pool structure inside the buffer */
CC_ListConf conf ; /* Create a new list config */
cc_list_conf_init ( & conf );
conf . mem_alloc = pool_malloc ; /* Set list memory allocators to pool allocators */
conf . mem_calloc = pool_calloc ;
conf . mem_free = pool_free ;
CC_List * list ;
cc_list_new_conf ( & conf , & list ); /* The newly created list will be allocated inside the "buffer" array*/
// Use the list
return 0 ;
}
Diese Pakete können normalerweise über den Paketmanager Ihrer Distribution installiert werden.
Um das Projekt zu erstellen, müssen wir zunächst ein separates Build-Verzeichnis erstellen (falls es noch nicht vorhanden ist):
mkdir build
Von diesem Verzeichnis aus können wir den Befehl cmake
ausführen und den Build konfigurieren:
cmake ..
oder cmake -DSHARED=True
um Collections-C als gemeinsam genutzte Bibliothek zu erstellencmake -DSHARED=False
um eine statische Bibliothek zu erstellen Sobald cmake
mit der Generierung der Makefiles fertig ist, können wir die Bibliothek erstellen, indem wir make
in unserem Build-Verzeichnis ausführen.
Ein Beispiel für das Klonen und Erstellen einer statischen Bibliothek:
git clone https://github.com/Collections-C.git
cd Collections-C
mkdir build
cd build
cmake -DSHARED=False
make
So führen Sie Tests aus (aus dem build
-Verzeichnis):
make test
Um einzelne Tests auszuführen, führen Sie einfach die entsprechende ausführbare Datei aus. Zum Beispiel:
build/test/array_test
Um die Bibliothek zu installieren, führen Sie Folgendes aus:
sudo make install
Standardmäßig werden die Bibliotheken und Header in den Verzeichnissen /usr/local/lib/
und /usr/local/include
installiert.
Sie müssen der Laufzeit des Systems den Speicherort der neuen Bibliothek mitteilen, um dynamisch verknüpfte Anwendungen ausführen zu können. Dies kann so einfach sein wie die Ausführung des folgenden Befehls, wenn Ihre /etc/ld.so.conf
das Installationsverzeichnis enthält.
Hinweis: macOS unterstützt ldconfig nicht.
sudo ldconfig
Wenn wir die Bibliothek bereits erstellt und installiert haben, können wir ein einfaches Hallo-Welt-Programm schreiben und es in einer Datei namens hello.c
speichern:
#include <stdio.h>
#include <collectc/cc_array.h>
int main ( int argc , char * * argv ) {
// Create a new array
CC_Array * ar ;
cc_array_new ( & ar );
// Add a string to the array
cc_array_add ( ar , "Hello World!n" );
// Retreive the string and print it
char * str ;
cc_array_get_at ( ar , 0 , ( void * ) & str );
printf ( "%s" , str );
return 0 ;
}
Jetzt müssen wir unser Programm kompilieren und verknüpfen. Da make
sowohl die statische als auch die dynamische Bibliothek erstellt, können wir auswählen, welche wir in unser Programm einbinden möchten.
Wenn wir die Bibliothek statisch mit unserem Programm verknüpfen möchten, können wir das Flag -static
an den Compiler übergeben
Hinweis: Unter macOS ist das Flag -static
nicht sehr benutzerfreundlich (es erfordert, dass alle Bibliotheken statisch verknüpft sind). Daher können wir -static -lcollectc
durch den vollständigen Pfad zur statischen Bibliothek ersetzen. Das ist standardmäßig /usr/local/lib/libcollectc.a
.
gcc hello.c -static -lcollectc -o hello
oder ähnlich beim Kompilieren mit clang:
clang hello.c -static -lcollectc -o hello
Dadurch wird die Bibliothek verknüpft, indem sie in die ausführbare Datei kopiert wird. Wir können diese Option verwenden, wenn wir Collections-C nicht als Laufzeitabhängigkeit haben möchten, allerdings geht dies auf Kosten der Generierung einer größeren ausführbaren Datei.
Wir können uns auch dafür entscheiden, zur Laufzeit dynamisch eine Verknüpfung mit der Bibliothek herzustellen. Dies ist das Standardverhalten, wenn das Compiler-Flag -static
weggelassen wird:
gcc hello.c -lcollectc -o hello
oder mit Klirren:
clang hello.c -lcollectc -o hello
Das dynamische Verknüpfen erzeugt eine kleinere ausführbare Datei, erfordert jedoch, dass libcollectc.so
auf jedem System vorhanden ist, auf dem das Programm ausgeführt werden soll.
Manchmal kann es für den Compiler schwierig sein, die Bibliothek oder die Header zu finden. Dies liegt normalerweise daran, dass sie im falschen Verzeichnis gesucht werden. Dies kann passieren, wenn die Bibliothek oder die Header oder beide in einem nicht standardmäßigen Verzeichnis oder überhaupt nicht installiert sind.
Wenn dies der Fall ist, können wir dem Compiler explizit mitteilen, wo er nach ihnen suchen soll, indem wir die Optionen -I[path to headers]
und -L[path to libraries]
übergeben:
gcc hello.c `pkg-config --cflags --libs collectionc` -o hello
Wenn bei der Kompilierung alles gut gelaufen ist, können wir die ausführbare Datei ausführen:
./hello
und es sollte Hello, World!
lauten. zur Konsole.
Beiträge sind willkommen.
Wenn Sie eine Funktionsanfrage haben oder einen Fehler gefunden haben, können Sie gerne ein neues Problem eröffnen. Wenn Sie Code beisteuern möchten, finden Sie weitere Informationen unter CONTRIBUTING.md.