Was ist der Unterschied zwischen:
ptr = malloc (MAXELEMS * sizeof(char *));
oder:
ptr = calloc (MAXELEMS, sizeof(char*));
Wann ist es eine gute Idee, calloc statt malloc zu verwenden oder umgekehrt?
Was ist der Unterschied zwischen:
ptr = malloc (MAXELEMS * sizeof(char *));
oder:
ptr = calloc (MAXELEMS, sizeof(char*));
Wann ist es eine gute Idee, calloc statt malloc zu verwenden oder umgekehrt?
malloc()
y calloc()
sind Funktionen aus der C-Standardbibliothek, die eine dynamische Speicherzuweisung ermöglichen, d. h., sie erlauben beide eine Speicherzuweisung während der Laufzeit.
Ihre Prototypen sind wie folgt:
void *malloc( size_t n);
void *calloc( size_t n, size_t t)
Es gibt hauptsächlich zwei Unterschiede zwischen den beiden:
Verhalten: malloc()
weist einen Speicherblock zu, ohne ihn zu initialisieren, und das Lesen des Inhalts aus diesem Block führt zu Garbage-Werten. calloc()
hingegen weist einen Speicherblock zu und initialisiert ihn mit Nullen, und das Lesen des Inhalts dieses Blocks führt natürlich zu Nullen.
Syntax: malloc()
benötigt 1 Argument (die zuzuweisende Größe), und calloc()
benötigt zwei Argumente (Anzahl der zuzuweisenden Blöcke und Größe der einzelnen Blöcke).
Der Rückgabewert von beiden ist ein Zeiger auf den zugewiesenen Speicherblock, falls erfolgreich. Andernfalls, NULL zurückgegeben, was das Scheitern der Speicherzuweisung anzeigt.
Beispiel:
int *arr;
// allocate memory for 10 integers with garbage values
arr = (int *)malloc(10 * sizeof(int));
// allocate memory for 10 integers and sets all of them to 0
arr = (int *)calloc(10, sizeof(int));
Die gleiche Funktionalität wie calloc()
kann erreicht werden durch malloc()
y memset()
:
// allocate memory for 10 integers with garbage values
arr= (int *)malloc(10 * sizeof(int));
// set all of them to 0
memset(arr, 0, 10 * sizeof(int));
Beachten Sie, dass malloc()
wird vorzugsweise verwendet über calloc()
da es schneller ist. Wenn eine Null-Initialisierung der Werte gewünscht ist, verwenden Sie calloc()
stattdessen.
Ein Unterschied, der noch nicht erwähnt wurde: Größenbeschränkung
void *malloc(size_t size)
kann nur bis zu SIZE_MAX
.
void *calloc(size_t nmemb, size_t size);
können bis zu etwa SIZE_MAX*SIZE_MAX
.
Diese Fähigkeit wird bei vielen Plattformen mit linearer Adressierung nicht oft genutzt. Solche Systeme begrenzen calloc()
con nmemb * size <= SIZE_MAX
.
Betrachten wir einen Typ von 512 Bytes namens disk_sector
und Code verwenden will Lose der Sektoren. Hier kann der Code nur bis zu SIZE_MAX/sizeof disk_sector
Sektoren.
size_t count = SIZE_MAX/sizeof disk_sector;
disk_sector *p = malloc(count * sizeof *p);
Betrachten Sie das folgende Beispiel, das eine noch größere Zuweisung ermöglicht.
size_t count = something_in_the_range(SIZE_MAX/sizeof disk_sector + 1, SIZE_MAX)
disk_sector *p = calloc(count, sizeof *p);
Ob ein solches System nun eine so große Menge liefern kann, ist eine andere Frage. Die meisten werden es heute nicht können. Dennoch ist es seit vielen Jahren so, dass SIZE_MAX
war 65535. Gegeben Mooresches Gesetz Ich vermute, dass dies um das Jahr 2030 bei bestimmten Speichermodellen der Fall sein wird. SIZE_MAX == 4294967295
und Speicherpools in der Größenordnung von 100 GBytes.
Im Allgemeinen ist size_t in der Lage, die Größe der größten Art von Objekt zu speichern, die ein Programm verarbeiten kann. Ein System, in dem size_t 32 Bits ist, wird wahrscheinlich nicht in der Lage sein, eine Zuweisung zu verarbeiten, die größer als 4294967295 Bytes ist, und ein System, das in der Lage wäre, Zuweisungen dieser Größe zu verarbeiten, würde fast sicher size_t
größer als 32 Bit. Die einzige Frage ist, ob die Verwendung von calloc
mit Werten, deren Produkt über SIZE_MAX
kann man sich darauf verlassen, dass sie Null ergibt, anstatt einen Zeiger auf eine kleinere Zuweisung zurückzugeben.
Zustimmen über Ihre Verallgemeinerung Die C-Spezifikation erlaubt jedoch calloc()
Zuweisungen, die über SIZE_MAX
. Das ist in der Vergangenheit mit 16-Bit-Produkten passiert. size_t
und da der Speicher immer billiger wird, sehe ich keinen Grund, warum dies nicht auch in Zukunft geschehen kann, selbst wenn es nicht gemeinsame .
Der C-Standard macht es möglich, dass Code Anfrage eine Zuteilung, deren Größe die SIZE_MAX
. Es ist sicherlich nicht erforderlich, dass es irgendeinen Umstand gibt, unter dem eine solche Zuweisung erfolgreich sein könnte; ich bin mir nicht sicher, ob es einen besonderen Nutzen hat, wenn man vorschreibt, dass Implementierungen, die solche Zuweisungen nicht handhaben können, Folgendes zurückgeben müssen NULL
(insbesondere angesichts der Tatsache, dass es bei einigen Implementierungen üblich ist, dass malloc
geben Zeiger auf Speicherplatz zurück, der noch nicht festgelegt wurde und möglicherweise nicht verfügbar ist, wenn der Code ihn tatsächlich zu nutzen versucht).
Beide malloc
y calloc
Speicher zuweisen, aber calloc
initialisiert alle Bits auf Null, während malloc
nicht.
Calloc könnte man als Äquivalent zu malloc + bezeichnen. memset
mit 0 (wobei memset die angegebenen Bits des Speichers auf Null setzt).
Wenn also eine Initialisierung auf Null nicht notwendig ist, könnte die Verwendung von malloc schneller sein.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
48 Stimmen
In C wirft man das Ergebnis von
malloc
Familie9 Stimmen
In C könnte man die obige Aufgabe allgemeiner formulieren als:
ptr = calloc(MAXELEMS, sizeof(*ptr));
8 Stimmen
Ein interessanter Beitrag über den Unterschied zwischen calloc und malloc+memset vorpus.org/blog/warum-besteht-calloc-exist
2 Stimmen
@ddddavidee Auch ich habe diesen Blog gefunden, nachdem ich mit so vielen Antworten im Netz unzufrieden war. Nathaniel J. Smith verdient 100+ SO Punkte für seine Analyse.
0 Stimmen
Verwandt: Kann calloc() insgesamt mehr als SIZE_MAX zuweisen?