5 Stimmen

Wie speichert ein Array-Zeiger seine Größe?

#include "stdio.h"

#define COUNT(a) (sizeof(a) / sizeof(*(a)))

void test(int b[]) {
  printf("2, Anzahl:%d\n", COUNT(b));
}

int main(void) {
  int a[] = { 1,2,3 };

  printf("1, Anzahl:%d\n", COUNT(a));
  test(a);

  return 0;
}

Das Ergebnis ist offensichtlich:

1, Anzahl:3
2, Anzahl:1

Meine Fragen:

  1. Wo wird die Längeninformation (Anzahl/Größe) gespeichert, wenn "a" deklariert wird?
  2. Warum geht die Längeninformation (Anzahl/Größe) verloren, wenn "a" an die Funktion test() übergeben wird?

8voto

AnT Punkte 300728

Es gibt im C-Sprach keine "Array-Pointer".

Die Größe wird nirgendwo gespeichert. a ist kein Zeiger, a ist ein Objekt vom Typ int[3], was dem Compiler zur Kompilierzeit bekannt ist. Also, wenn Sie den Compiler bitten, sizeof(a) / sizeof(*a) zur Kompilierzeit zu berechnen, weiß der Compiler, dass die Antwort 3 ist.

Wenn Sie Ihr a an die Funktion übergeben, bitten Sie den Compiler ausdrücklich, den Arraytyp in den Zeigertyp umzuwandeln (da Sie den Funktionparameter als Zeiger deklariert haben). Für Zeiger produziert Ihr sizeof Ausdruck ein völlig anderes Ergebnis.

4voto

Michael Burr Punkte 320591
  1. Wo wird die Längen(informations-)angabe gespeichert, wenn "a" deklariert wird?

Es wird nirgendwo gespeichert. Der sizeof-Operator (der in der COUNT()-Makro verwendet wird) gibt die Größe des gesamten Arrays zurück, wenn er als Operand ein echtes Array erhält (wie beim ersten printf()).

  1. Warum geht die Längen(informations-)angabe verloren, wenn "a" an die test()-Funktion übergeben wird?

Leider sind in C Arrays, die als Parameter an Funktionen übergeben werden, eine Fiktion. Arrays werden nicht an Funktionen übergeben; der Parameter wird als Zeiger behandelt, und das Array-Argument, das im Funktionsaufruf übergeben wird, wird zu einem einfachen Zeiger 'zerfallen'. Der sizeof-Operator gibt die Größe des Zeigers zurück, die keine Korrelation zur Größe des Arrays hat, das als Argument verwendet wurde.

Als Randnotiz, in C++ können Sie einen Funktionsparameter als Referenz zu einem Array haben, und in diesem Fall wird der vollständige Array-Typ der Funktion zur Verfügung gestellt (d. h. das Argument zerfällt nicht in einen Zeiger und sizeof gibt die Größe des gesamten Arrays zurück). Allerdings muss das Argument in diesem Fall genau dem Arraytyp entsprechen (einschließlich der Anzahl von Elementen), was die Technik größtenteils nur mit Vorlagen nützlich macht.

Zum Beispiel wird das folgende C++-Programm das Erwartete tun:

#include "stdio.h"

#define COUNT(a) (sizeof(a) / sizeof(*(a)))

template 
void test(int (&b)[T]) {
  printf("2, count:%d\n", COUNT(b));
}

int main(int argc, char *argv[]) {
  int a[] = { 1,2,3 };

  printf("1, count:%d\n", COUNT(a));
  test(a);

  return 0;
}

1voto

Jonathan Leffler Punkte 694013
  1. Nirgendwo.
  2. Weil es nicht zuerst gespeichert wurde.

Wenn Sie im main() auf das Array verweisen, ist die tatsächliche Array-Deklaration -Definition sichtbar, sodass sizeof(a) die Größe des Arrays in Bytes angibt.

Wenn Sie im Funktion auf das Array verweisen, ist der Parameter effektiv 'void test(int *b)', und die Größe des Zeigers geteilt durch die Größe des darauf verweisenden Elements beträgt auf einer 32-Bit-Plattform zufällig 1, während es auf einer 64-Bit-Plattform mit der LP64-Architektur 2 wäre (oder auch auf einer LLP64-Plattform wie Windows-64), weil Zeiger 8 Bytes und int 4 Bytes sind.

Es gibt keine universelle Methode, um die Größe eines in eine Funktion übergebenen Arrays zu bestimmen; Sie müssen es explizit und manuell übergeben.


Vom Kommentar:

Ich habe immer noch zwei Fragen:

  1. Was meinen Sie mit "..die tatsächliche Deklaration ist sichtbar.."? Könnte der Compiler (oder das Betriebssystem) die Längeninformation durch die Funktion sizeof(a) erhalten?
  2. Warum enthält der Zeiger &(a[0]) nicht die Längeninformation wie der Zeiger "a"?
  1. Ich denke, Sie haben Java gelernt, bevor Sie C gelernt haben oder eine andere modernere Sprache. Letztendlich kommt es darauf an, "weil das so definiert ist in C". Das Betriebssystem ist nicht beteiligt; dies ist ein rein compilerbezogenes Problem.

    • sizeof() ist ein Operator, kein Funktionsaufruf. Sofern Sie es nicht mit einem VLA (variabel lange Array) zu tun haben, wird es zur Kompilierzeit ausgewertet und ist ein konstanter Wert.

    In main() ist die Array-Definition dort, und wenn der sizeof()-Operator auf den Namen eines tatsächlichen Arrays angewendet wird - im Gegensatz zu einem Array-Parameter einer Funktion - wird die zurückgegebene Größe die Größe des Arrays in Bytes sein.

  2. Weil dies C und nicht Algol, Pascal, Java, C #, ... ist

    C speichert die Größe des Arrays nicht - Punkt. Das ist eine Tatsache. Und wenn ein Array an eine Funktion übergeben wird, wird die Größeninformation nicht an die Funktion übergeben; das Array 'zerfällt' zu einem Zeiger auf das nullte Element des Arrays - und nur dieser Zeiger wird übergeben.

1voto

Jonathan Wood Punkte 61798
1. Wo wird die Längen(zähl/Größen)-Information gespeichert, wenn "a" deklariert wird?

Sie wird nicht gespeichert. Der Compiler weiß, was a ist und kennt daher seine Größe. Der Compiler kann also sizeof() durch die tatsächliche Größe ersetzen.

2. Warum geht die Längen(zähl/Größen)-Information verloren, wenn "a" an die Funktion test() übergeben wird?

In diesem Fall wird b als Zeiger deklariert (auch wenn er auf a zeigen kann). Wenn ein Zeiger vorhanden ist, kennt der Compiler die Größe der darauf zeigenden Daten nicht.

0voto

Prasoon Saurav Punkte 88056
  1. Wo wird die Längen(zähl-/Größe)-Information gespeichert, wenn "a" deklariert wird?

Nirgendwo. Übrigens, die Frage ergibt keinen Sinn.

  1. Warum geht die Längen(zähl-/Größe)-Information verloren, wenn "a" an die Funktion test() übergeben wird?

Ein Array wandelt sich in einen Zeiger(der auf das erste Element zeigt) um, wenn es an eine Funktion übergeben wird. Also ist die Antwort 'nirgendwo' und ähnlich wie bei der vorherigen Frage ergibt auch diese keinen Sinn.

CodeJaeger.com

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.

Powered by:

X