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.)
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.
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.
“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 fehlschlagenNULL
. 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ößen * sizeof *p
. Diese Speicherblockgröße kann überschritten werdenSIZE_MAX
. Aber dannp
ist kein Arrayn
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