Erfordert der C-Standard, dass die Größe eines Arrays aus n Elementen das n-fache der Größe eines Elements ist?

Lesezeit: 6 Minuten

Benutzer-Avatar
Eric Postpischil

Erfordert der C-Standard, dass die Größe eines Arrays von n Elemente sein n mal die Größe eines Elements, entweder durch explizite Aussage oder durch rigorose logische Ableitung aus seinen Anforderungen?

Könnte zum Beispiel int (*x)[5] = malloc(5 * sizeof **x); versäumen es, ausreichend Platz für ein Array von fünf anzufordern int?

C 2011 [N1570] 6.5.3.4 7 zeigt ein Beispiel für die Berechnung der Anzahl der Elemente in einem Array als sizeof array / sizeof array[0]. Beispiele sind jedoch kein normativer Bestandteil des Standards (gemäß Absatz 8 des Vorworts).

6.2.5 20 sagt, dass ein Array-Typ eine zusammenhängend zugewiesene, nicht leere Menge von Objekten mit einem bestimmten Typ beschreibt, aber nichts über den gesamten erforderlichen Speicher sagt.

Dies ist lediglich eine sprachliche Anwaltsfrage; tatsächliche Implementierungen sind irrelevant. (Um diejenigen zu besänftigen, die konkrete Beispiele wollen, stellen Sie eine C-Implementierung auf, die eine zusätzliche Speicherverwaltung für große Arrays erfordert, sodass zum Erstellen eines Arrays einige zusätzliche Daten erstellt werden müssen, um den Speicher zu verwalten.)

  • “könnte int (*x)[5] = malloc(5 * sizeof **x); es versäumen, ausreichend Platz für ein Array von fünf int anzufordern” klingt ebenso unklar wie offensichtlich a malloc() Anfrage könnte durch Rückgabe fehlschlagen NULL. Vielleicht muss die Frage umformuliert werden.

    – chux – Wiedereinsetzung von Monica

    28. November 2017 um 2:05 Uhr


  • @chux: Deshalb habe ich „Fehler beim Anfordern“ und nicht „Fehler beim Zuweisen“ geschrieben. Sicher, die Zuweisung kann fehlschlagen, aber die Anfrage wurde gestellt. Hat es genug angefordert oder hat es nicht genug angefordert?

    – Eric Postpischil

    28. November 2017 um 2:16 Uhr

  • Hmmm, Code kann per vergeben werden p = calloc(n, sizeof *p) ein Speicherblock der Größe n * sizeof *p. Diese Speicherblockgröße kann überschritten werden SIZE_MAX. Aber dann p ist kein Array n von T, nur ein Zeiger auf T. Ich denke also nicht, dass dies als Gegenbeispiel geeignet ist.

    – chux – Wiedereinsetzung von Monica

    28. November 2017 um 2:29 Uhr


  • Wow, ich habe schon einige Sprachanwälte gesehen (und war selbst einer von ihnen), aber die Größe eines Arrays in Frage zu stellen, ist eine ganz andere Ebene!

    – Benutzer541686

    28. November 2017 um 3:09 Uhr


  • Ich sehe hier nichts, was über die Möglichkeit spricht, dass das Array einen Header haben könnte.

    – Heiße Licks

    28. November 2017 um 3:34 Uhr

Benutzer-Avatar
ad absurdum

Ja, es ist erforderlich, dass die Größe eines Arrays T[n] sein n * sizeof (T).

Der Standard definiert Arrays in §6.2.5/20:

Ein Array-Typ beschreibt eine zusammenhängend zugewiesene, nicht leere Menge von Objekten mit einem bestimmten Mitgliedsobjekttyp….

Weiterhin die sizeof Operator liefert die Gesamtzahl der Bytes im Array(§6.5.3.4/4):

Wann Größe von …. auf einen Operanden vom Typ Array angewendet wird, ist das Ergebnis die Gesamtzahl der Bytes im Array. Bei Anwendung auf einen Operanden vom Typ Struktur oder Union ist das Ergebnis die Gesamtzahl der Bytes in einem solchen Objekt, einschließlich interner und abschließender Auffüllung.

Da ein Array aus einer zusammenhängenden Zuordnung von Objekten besteht, kann es kein internes Padding geben. Und da wird bezüglich der nachlaufenden Polsterung explizit erwähnt sizeof -Operator nur im Kontext von Unions und Strukturen, scheint es klar, dass Arrays kein solches abschließendes Padding besitzen sollten.

Beachten Sie abschließend, dass in §6.2.6.1/4 heißt es:

Werte, die in Nicht-Bitfeld-Objekten eines beliebigen anderen Objekttyps gespeichert sind, bestehen aus n x CHAR_BIT Bits, wo n ist die Größe eines Objekts dieses Typs in Byte. Der Wert kann in ein Objekt des Typs kopiert werden unsigned char [n] (z. B. von memcpy); Die resultierende Gruppe von Bytes wird als the bezeichnet Objektdarstellung des Wertes.

Angenommen, dass Arrays könnte nachgestellte Füllbytes haben, betrachten Sie ein Array unsigned char A[n]und betrachten Sie das Array weiter unsigned char B[sizeof A]zu dem alle Bytes (einschließlich möglicher Füllbytes) von A[] kopiert wurden. Jetzt, A[] muss gleich groß sein wie B[]seit (§6.2.6.1/8):

Wenn ein Operator auf einen Wert angewendet wird, der mehr als eine Objektdarstellung hat, wirkt sich die verwendete Objektdarstellung nicht auf den Wert des Ergebnisses aus.

Dies würde das bedeuten B[] muss kein abschließendes Auffüllen haben, was bedeuten würde, dass Arrays nachgestellte Füllbytes haben können, außer unter bestimmten besonderen Bedingungen, die nirgendwo im Standard erwähnt werden, oder alternativ, dass Arrays nachgestelltes Auffüllen haben können, außer Arrays von unsigned char. Da im Standard keine dieser Möglichkeiten erwähnt wird, liegt der Schluss nahe, dass Arrays von vornherein kein nachlaufendes Padding haben dürfen.

  • Siehe meine Kommentare zur Antwort von R..; sie gelten auch hier – ich finde die gut.

    – Eric Postpischil

    28. November 2017 um 1:53 Uhr

  • Folge: Auf Plattformen, die eine Ausrichtung erfordern, ist sizeof(struct {int x; char y;}) == sizeof(struct {int x; int y;})

    – Josua

    28. November 2017 um 3:59 Uhr

  • @Joshua – nicht sicher, ob ich dir hierher folge. Jeder dieser Strukturen kann eine beliebige Füllmenge hinzugefügt werden.

    – ad absurdum

    28. November 2017 um 4:08 Uhr

  • @DavidBowling: Ah ja, wenn der Compiler zum Teufel Padding hinzufügt, wird es nicht halten, aber ich habe noch keinen Compiler gesehen, der Padding zum Teufel hinzufügt.

    – Josua

    28. November 2017 um 4:16 Uhr

  • @Joshua – in der Tat, aber ich bin immer vorsichtig, die zu treffen Todesstation 9000 in einer dunklen Gasse.

    – ad absurdum

    28. November 2017 um 4:20 Uhr

Der einzige Text, der die Darstellung von Arrays beschreibt, ist ziemlich knapp und befindet sich in dem, was Sie unter 6.2.5 ¶20 gefunden haben:

Aus den Objekt- und Funktionstypen können beliebig viele abgeleitete Typen wie folgt konstruiert werden:

  • Ein Array-Typ beschreibt eine zusammenhängend zugewiesene, nicht leere Menge von Objekten mit einem bestimmten Mitgliedsobjekttyp, der als Elementtyp bezeichnet wird. Der Elementtyp muss vollständig sein, wenn der Array-Typ angegeben wird. Array-Typen werden durch ihren Elementtyp und durch die Anzahl der Elemente im Array charakterisiert. Ein Array-Typ wird von seinem Elementtyp abgeleitet, und wenn sein Elementtyp T ist, wird der Array-Typ manchmal als „Array von T“ bezeichnet. Die Konstruktion eines Array-Typs aus einem Elementtyp wird als „Array-Typ-Ableitung“ bezeichnet.

Beachten Sie, dass es nicht so etwas wie “zusammenhängend zugewiesene, nicht leere Menge von Objekten und Polsterung” sagt, also das Array ist nur die Objekte. Es scheint also keine Grundlage für eine solche Behauptung zu geben sizeof das Array [type] könnte zu einem anderen Ergebnis als der Größe der zusammenhängenden Menge von Objekten führen, was offensichtlich ist N mal die Größe des einzelnen Elementtyps.

Es ist auch erwähnenswert, dass Padding nicht etwas ist, das einfach alleine existieren kann, weil es nicht spezifiziert ist, dass es nicht existiert. C spezifiziert Repräsentationen von Typen (6.2.6) und spezifiziert explizit die Möglichkeit, Bits und Bytes aufzufüllen, wo es angemessen ist. Es gibt keinen Text über das Auffüllen von Arrays und ist daher nicht Teil ihrer Darstellung.

  • Zuerst dachte ich, das Wort „beschreibt“ hätte etwas Spielraum, denn wenn ein Array die Objekte „beschreibt“, werden sicherlich einige Daten benötigt, um diese Beschreibung bereitzustellen. Aber wenn ich es noch einmal lese, denke ich, dass es bedeutet, dass die Worte „Array-Typ“ eine Beschreibung des Typs sind. Somit besteht das Array aus den Objekten.

    – Eric Postpischil

    28. November 2017 um 1:49 Uhr

  • Natürlich glaube ich, dass die Absicht dieser Passage und der in David Bowlings Antwort zitierten darin besteht, ein Array nur aus den Objekten zu erstellen, und diese Antworten bringen mich der Annahme näher, dass der Standard dies erreicht, ohne das Ziel zu verfehlen. Nicht ganz die formale Aussage, die der Mathematiker in mir will, aber nah dran. Ich werde sehen, was sich für ein oder zwei Tage entwickelt, und dann wahrscheinlich eine Antwort akzeptieren.

    – Eric Postpischil

    28. November 2017 um 1:52 Uhr

1367450cookie-checkErfordert der C-Standard, dass die Größe eines Arrays aus n Elementen das n-fache der Größe eines Elements ist?

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

Privacy policy