Hier ist zunächst ein Code:
int main()
{
int days[] = {1,2,3,4,5};
int *ptr = days;
printf("%u\n", sizeof(days));
printf("%u\n", sizeof(ptr));
return 0;
}
Gibt es eine Möglichkeit, die Größe des Arrays herauszufinden, auf das verwiesen ptr
wird (anstatt nur seine Größe anzugeben, die auf einem 32-Bit-System vier Bytes beträgt)?
Antworten:
Nein, das kannst du nicht. Der Compiler weiß nicht, auf was der Zeiger zeigt. Es gibt Tricks, wie das Beenden des Arrays mit einem bekannten Out-of-Band-Wert und das anschließende Zählen der Größe bis zu diesem Wert, aber das wird nicht verwendet
sizeof()
.Ein weiterer Trick ist der von Zan erwähnte , der darin besteht, die Größe irgendwo zu verstauen. Wenn Sie beispielsweise das Array dynamisch zuweisen, weisen Sie einem Block einen int zu, der größer als der von Ihnen benötigte ist, speichern Sie die Größe im ersten int und kehren Sie
ptr+1
als Zeiger auf das Array zurück. Wenn Sie die Größe benötigen, dekrementieren Sie den Zeiger und sehen Sie sich den versteckten Wert an. Denken Sie daran, den gesamten Block von Anfang an freizugeben und nicht nur das Array.quelle
Die Antwort ist nein."
C-Programmierer speichern die Größe des Arrays irgendwo. Es kann Teil einer Struktur sein, oder der Programmierer kann ein bisschen und
malloc()
mehr Speicher als angefordert betrügen , um einen Längenwert vor dem Start des Arrays zu speichern.quelle
Für dynamische Arrays ( malloc oder C ++ new ) müssen Sie die Größe des Arrays wie von anderen erwähnt speichern oder eine Array-Manager-Struktur erstellen, die das Hinzufügen, Entfernen, Zählen usw. handhabt. Leider macht C dies bei weitem nicht so gut wie C ++, da Sie es grundsätzlich für jeden unterschiedlichen Array-Typ erstellen müssen, den Sie speichern. Dies ist umständlich, wenn Sie mehrere Arten von Arrays verwalten müssen.
Für statische Arrays, wie das in Ihrem Beispiel, wird ein allgemeines Makro verwendet, um die Größe zu ermitteln. Es wird jedoch nicht empfohlen, da nicht überprüft wird, ob der Parameter wirklich ein statisches Array ist. Das Makro wird jedoch in echtem Code verwendet, z. B. in den Linux-Kernel-Headern, obwohl es sich geringfügig von dem folgenden unterscheiden kann:
Sie können aus Gründen googeln, um sich vor solchen Makros in Acht zu nehmen. Achtung.
Wenn möglich, die C ++ stdlib wie Vektor, die viel sicherer und einfacher zu bedienen ist.
quelle
ARRAY_SIZE
Makro funktioniert immer, wenn sein Argument ein Array ist (dh ein Ausdruck vom Array-Typ). Für Ihr sogenanntes "dynamisches Array" erhalten Sie nie ein tatsächliches "Array" (Ausdruck des Array-Typs). (Dies ist natürlich nicht möglich, da Array-Typen beim Kompilieren ihre Größe angeben.) Sie erhalten lediglich einen Zeiger auf das erste Element. Ihr Einwand "prüft nicht, ob der Parameter wirklich ein statisches Array ist" ist nicht wirklich gültig, da sie sich unterscheiden, da eines ein Array ist und das andere nicht.Es gibt eine saubere Lösung mit C ++ - Vorlagen, ohne sizeof () zu verwenden . Die folgende Funktion getSize () gibt die Größe eines statischen Arrays zurück:
Hier ist ein Beispiel mit einer foo_t- Struktur:
Ausgabe:
quelle
T (&)[SIZE]
. Können Sie erklären, was das bedeutet? In diesem Zusammenhang könnte man auch constexpr erwähnen.SIZE
als Argument übergeben, sondern als Vorlagenparameter bereits durch die Funktionsdefinition bekannt sein.)Für dieses spezielle Beispiel gibt es ja, wenn Sie typedefs verwenden (siehe unten). Wenn Sie dies auf diese Weise tun, können Sie natürlich auch SIZEOF_DAYS verwenden, da Sie wissen, auf was der Zeiger zeigt.
Wenn Sie einen (void *) - Zeiger haben, wie er von malloc () oder dergleichen zurückgegeben wird, gibt es keine Möglichkeit, die Datenstruktur zu bestimmen, auf die der Zeiger zeigt, und daher auch keine Möglichkeit, seine Größe zu bestimmen.
Ausgabe:
quelle
Wie in allen richtigen Antworten angegeben, können Sie diese Informationen nicht allein aus dem verfallenen Zeigerwert des Arrays abrufen. Wenn der verfallene Zeiger das von der Funktion empfangene Argument ist, muss die Größe des Ursprungsarrays auf eine andere Weise angegeben werden, damit die Funktion diese Größe erkennt.
Hier ist ein anderer Vorschlag als der bisher bereitgestellte, der funktionieren wird: Übergeben Sie stattdessen einen Zeiger auf das Array. Dieser Vorschlag ähnelt den Vorschlägen im C ++ - Stil, außer dass C keine Vorlagen oder Verweise unterstützt:
Dieser Vorschlag ist jedoch für Ihr Problem etwas albern, da die Funktion so definiert ist, dass sie genau die Größe des übergebenen Arrays kennt (daher muss sizeof überhaupt nicht für das Array verwendet werden). Was es jedoch tut, ist eine gewisse Typensicherheit. Es verhindert, dass Sie ein Array mit einer unerwünschten Größe übergeben.
Wenn die Funktion in der Lage sein soll, mit einer beliebigen Arraygröße zu arbeiten, müssen Sie die Größe der Funktion als zusätzliche Information angeben.
quelle
Es gibt keine magische Lösung. C ist keine reflektierende Sprache. Objekte wissen nicht automatisch, was sie sind.
Aber Sie haben viele Möglichkeiten:
quelle
Meine Lösung für dieses Problem besteht darin, die Länge des Arrays in einem Struktur-Array als Metainformation über das Array zu speichern.
Sie müssen sich jedoch darum kümmern, die richtige Länge des Arrays festzulegen, das Sie speichern möchten, da dies keine Möglichkeit ist, diese Länge zu überprüfen, wie unsere Freunde massiv erklärt haben.
quelle
Sie können so etwas tun:
quelle
Nein, Sie können nicht ermitteln,
sizeof(ptr)
auf welche Größe das Arrayptr
zeigt.Das Zuweisen von zusätzlichem Speicher (mehr als die Größe des Arrays) ist jedoch hilfreich, wenn Sie die Länge in zusätzlichem Speicherplatz speichern möchten.
quelle
Die Größe der Tage [] beträgt 20, was keiner der Elemente entspricht. * Größe des Datentyps. Während die Größe des Zeigers 4 ist, egal auf was er zeigt. Weil ein Zeiger auf ein anderes Element zeigt, indem er dessen Adresse speichert.
quelle
ARRAY_SIZE ist vorbei an der Größe variabel:
Verwendung ist:
quelle
In Strings befindet
'\0'
sich am Ende ein Zeichen, sodass die Länge des Strings mit Funktionen wie ermittelt werden kannstrlen
. Das Problem mit einem ganzzahligen Array besteht beispielsweise darin, dass Sie keinen Wert als Endwert verwenden können. Eine mögliche Lösung besteht darin, das Array zu adressieren und denNULL
Zeiger als Endwert zu verwenden .quelle
NULL
ist wahrscheinlich die am wenigsten effiziente Alternative zumsize
direkten Speichern eines separaten Elements . Vor allem , wenn Sie tatsächlich nutzen diese zusätzliche Schicht Indirektionsebene die ganze Zeit.