Zwei Argumente für calloc

Lesezeit: 7 Minuten

Warum tut calloc Nehmen Sie zwei Argumente anstelle von einem wie malloc?

Insbesondere, da zwischen den folgenden Ausdrücken kein Unterschied besteht (oder besteht?):

calloc (a, b);
calloc (b, a);
calloc (a * b, 1);
calloc (1, a * b);

Warum nicht einfach die Gesamtzahl der zuzuweisenden Bytes akzeptieren? Was ist der Grundgedanke hinter dieser Schnittstelle? Und warum gilt das nicht für malloc?

  • Siehe Ist calloc(4, 6) dasselbe wie calloc(6, 4) ?.

    – Matthäus Flaschen

    3. November 2010 um 3:58 Uhr

  • @Matthew Danke! Ich hatte keine Ahnung davon.

    – Sanjoyd

    3. November 2010 um 14:54 Uhr

AnT steht mit Russlands Benutzer-Avatar
AnT steht zu Russland

Ich habe zwei gehört [mutually exclusive] Erklärungen dafür, warum es zwei Argumente hat:

  1. calloc übernimmt die Verantwortung für die Prüfung auf Überlauf bei der Multiplikation. Wenn die Gesamtgröße des angeforderten Blocks zu groß ist (z. B. overflows size_t), calloc gibt einen Nullzeiger zurück, um einen Fehler anzuzeigen. Mit malloc Sie müssen selbst auf Überlauf achten, was viele Menschen einfach vergessen. (Obwohl die Geschichte der Standardbibliothek Beispiele dafür kennt calloc Implementierungen, die den Überlauf ignorierten und daher nicht korrekt funktionierten).

  2. calloc ermöglicht es tatsächlich, größere Speicherblöcke als den Typbereich zuzuweisen size_tdh calloc möglicherweise in der Lage sein, die richtige nicht überlaufende große Multiplikation seiner Argumente durchzuführen und den Block der resultierenden Größe zuzuweisen. Aus diesem Grund seit calloc verwendet zwei Argumente vom Typ size_tes kann größere Blöcke zuweisen als malloc jemals in der Lage sein werden (seit malloc akzeptiert nur ein Argument vom Typ size_t).

Ich habe immer geglaubt, dass die erste Erklärung die richtige ist. Nachdem ich jedoch einige Beiträge hier auf SO gelesen habe, habe ich meine Zweifel.

  • -1, technisch gesehen können Sie nicht mehr gleich und ungefähr als den maximalen Wert in zuweisen size_t weil es eine Systemgrenze ist, und in anderen Punkten wird dies keinen Sinn machen. Auf 32-Bit-Rechnern versuchen Sie, alle möglichen Adressräume zuzuweisen, dies ist unmöglich, auf 64-Bit-Rechnern schlägt dies ebenfalls fehl.

    – Svisstack

    3. November 2010 um 3:16 Uhr


  • (1) klingt für mich als Begründung sicherlich plausibler. (2) könnte jedoch eine (möglicherweise unbeabsichtigte) Folge des Standards sein. Macht es viel Sinn, eine zuordnen zu können int[SIZE_MAX] durch calloc, obwohl Sie sicherlich keinen als Mitglied einer Struktur deklarieren können (weil sizeof wäre nicht in der Lage, es zu messen)?

    – Steve Jessop

    3. November 2010 um 3:18 Uhr

  • @Svisstack: Genau das habe ich mir gerade im Standard angesehen, ich denke, AndreyT spricht einen interessanten Punkt an. size_t ist als der Typ definiert, der von zurückgegeben wird sizeof. Nicht eigentlich als maximale Größe eines Objekts. Es gibt Objekte, auf die Sie sich nicht bewerben können sizeof, insbesondere dynamisch zugewiesene Arrays. Ich glaube nicht, dass der Ausdruck “Systemgrenze” im Standard vorkommt. Ich denke, man muss es besser machen als „es schlägt auf meinem 64-Bit-System fehl“, wenn man demonstrieren will, dass das in (2) beschriebene Setup eigentlich vom Standard verboten ist.

    – Steve Jessop

    3. November 2010 um 3:20 Uhr


  • @Svisstack: Ich spreche vom C-Standard. Ich weiß wirklich, wovon ich spreche, wenn es um den Unterschied zwischen einem Standard und bestimmten Implementierungen des Standards geht. Es geht überhaupt nicht darum, wie ich “will” calloc implementiert werden – ich fände es besser, wenn die seltsame Sache, die AndreT aufwirft, vom Standard verboten wäre. Ich sehe einfach nicht, wo es ist. Wenn Sie nur sagen, dass die Option (2) von AndreyT nicht auf Ihren PC zutrifft, dann haben Sie recht. Aber die Frage bezieht sich explizit auf die Gründe für den C-Standard, nicht auf Ihren PC.

    – Steve Jessop

    3. November 2010 um 3:42 Uhr


  • @Svisstack Der C-Standard hat nie gesagt, dass er nur mit Standardmaschinen verwendet werden soll. Jemand könnte sehr gut einen C-Compiler für sein Super-Rechenzentrum schreiben, in dem sehr große Speicherzuweisungen tatsächlich sinnvoll sind.

    – Grafik-Noob

    3. November 2010 um 4:03 Uhr

Ich glaube, dass malloc garantiert einen Speicherbereich zurückgibt, der gemäß der gröbsten Anforderung ausgerichtet ist, die mit der durch das zweite Argument angegebenen Größe kompatibel wäre. Wenn das System beispielsweise eine Ausrichtung von 2- und 4-Byte-Ganzzahlen erfordert und das zweite Argument 10 ist, muss der zurückgegebene Zeiger an einer Zwei-Byte-Grenze ausgerichtet werden; Wenn das zweite Argument 12 wäre, würde der Zeiger an einer Vier-Byte-Grenze ausgerichtet werden. Ich vermute, dass viele Systeme in der Praxis alle zurückgegebenen Zeiger an der größten möglicherweise erforderlichen Grenze ausrichten, unabhängig von der Größe, aber ich glaube nicht, dass dies erforderlich ist, außer für calloc.

Der einzige bemerkenswerte Unterschied ist der calloc ist erforderlich, um den zugewiesenen Speicherplatz auf Nullen zu initialisieren, obwohl es keine solche Garantie gibt malloc. Ansonsten denke ich, dass es nur aus historischen Gründen zwei verschiedene Funktionen gibt.

  • Außer dass calloc kann schneller sein als a malloc gefolgt von einem memset.

    – Sanjoyd

    3. November 2010 um 3:18 Uhr

Alles sind nur Bytes ist eine relativ neue (dh c/Unix-Ära) Erfindung – auf vielen anderen Architekturen waren die Dinge Datensätze mit fester Größe.

Benutzeravatar von Svisstack
Svisstack

calloc(x,y) ist ein Äquivalent zu malloc(x*y)

Aber calloc tut zusätzlich (Werte auf 0 setzen mit) memset(block, 0, x*y)

Diese Funktion ist nur für den hübschen Weg vorbei Größe des Elements und Anzahl der Elementewenn Sie in malloc diese Werte multiplizieren müssen, um die erforderliche Anzahl von Bytes zu erhalten, prüft diese Funktion auch den Ganzzahlüberlauf bei der Multiplikation.

Wenn Sie beispielsweise Speicher für 12 Ganzzahlen zuweisen möchten und etwas mit diesen Ganzzahlen tun möchten und Sie ihre Werte auf 0 gesetzt haben müssen, verwenden Sie calloc(12, sizeof(int))

Aber wenn Sie einen Speicherblock (256 Bytes) zuweisen möchten, um in Zukunft eine Zeichenfolge zu kopieren memset Ist eine für Sie nicht nutzbar, dann ist eine bessere Nutzung sinnvoll malloc(sizeof(char) * 256) oder zum Beispiel malloc(sizeof(wchar_t) * 256)


void *
calloc (size_t nmemb, size_t lsize)
{
  void *ptr;
  struct __meminfo *info;
  size_t size = lsize * nmemb;

  /* if size overflow occurs, then set errno to ENOMEM and return NULL */
  if (nmemb && lsize != (size / nmemb))
    {
      set_errno (ENOMEM);
      return NULL;
    }

  /* allocate memory */
  ptr = malloc (size);

  /* get pointer to info part of chunk */
  info = __mem2info (ptr);

  /* fill memory with zeros and set __MEM_CALLOC flag */
  memset (ptr, 0, info->size);
  info->flags |= __MEM_CALLOC;

  return ptr;                   /* happy end */
}

  • Kleiner Ärger: sizeof(char) ist per Definition 1.

    – Ben Jackson

    3. November 2010 um 3:14 Uhr

  • Seien Sie vorsichtig mit dem ganzzahligen Überlauf bei der Multiplikation.

    – jamesdlin

    3. November 2010 um 3:17 Uhr

  • Diese Funktion dient nur dazu, die Größe des Elements und die Anzahl der Elemente zu übergeben, wenn Sie in malloc diese Werte multiplizieren müssen, um die erforderliche Anzahl von Bytes zu erhalten. -> Warum haben wir also keine ähnliche Schnittstelle zu malloc?

    – Sanjoyd

    3. November 2010 um 3:17 Uhr


  • @theDigtialEngel: Dies ist keine smillar-Schnittstelle, diese Funktion ist eine Abkürzung zum Delarieren eines Arrays einiger Vektoren, wenn Sie alle Werte auf Null gesetzt haben müssen. An anderer Stelle, warum nicht?

    – Svisstack

    3. November 2010 um 3:21 Uhr

  • Das Lustige ist, dass die Schnittstelle zu calloc (Ich spreche von dem Array von Vektoren, nicht vom Speicher-Null-Teil) ist nicht einmal eine Abkürzung; calloc (a, b) und calloc (a * b) haben die gleiche Anzahl von Zeichen. Tatsächlich ist im ersten Fall die Zuweisung nur eines Elements (calloc (a, 1)) ist unnötig kompliziert.

    – Sanjoyd

    3. November 2010 um 3:24 Uhr

  • Kleiner Ärger: sizeof(char) ist per Definition 1.

    – Ben Jackson

    3. November 2010 um 3:14 Uhr

  • Seien Sie vorsichtig mit dem ganzzahligen Überlauf bei der Multiplikation.

    – jamesdlin

    3. November 2010 um 3:17 Uhr

  • Diese Funktion dient nur dazu, die Größe des Elements und die Anzahl der Elemente zu übergeben, wenn Sie in malloc diese Werte multiplizieren müssen, um die erforderliche Anzahl von Bytes zu erhalten. -> Warum haben wir also keine ähnliche Schnittstelle zu malloc?

    – Sanjoyd

    3. November 2010 um 3:17 Uhr


  • @theDigtialEngel: Dies ist keine smillar-Schnittstelle, diese Funktion ist eine Abkürzung zum Delarieren eines Arrays einiger Vektoren, wenn Sie alle Werte auf Null gesetzt haben müssen. An anderer Stelle, warum nicht?

    – Svisstack

    3. November 2010 um 3:21 Uhr

  • Das Lustige ist, dass die Schnittstelle zu calloc (Ich spreche von dem Array von Vektoren, nicht vom Speicher-Null-Teil) ist nicht einmal eine Abkürzung; calloc (a, b) und calloc (a * b) haben die gleiche Anzahl von Zeichen. Tatsächlich ist im ersten Fall die Zuweisung nur eines Elements (calloc (a, 1)) ist unnötig kompliziert.

    – Sanjoyd

    3. November 2010 um 3:24 Uhr

1388640cookie-checkZwei Argumente für calloc

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy