Warum ist sizeof(param_array) die Größe des Zeigers?

Lesezeit: 4 Minuten

Ich möchte die Länge eines Arrays erhalten, sagen wir int array[] = {1, 2, 3, 4}. ich benutzte sizeof das zu tun.

int length(int array[])
{
     return sizeof(array) / sizeof(int);
}

int main()
{
    int array[] = {1, 2, 3, 4};
    printf("%d\n", length(array)); // print 1
    printf("%d\n", sizeof(array) / sizeof(int)); // print 4
}

Also, warum die sizeof(array) in Funktion length gibt die Zeigergröße von zurück array? Aber in Funktion mainEs klappt.

Und wie soll ich die ändern length Funktion, um die Länge eines Arrays zu erhalten?

  • Ja, ich weiß, dass dies eine C++-Frage ist, aber sie enthält auch sehr nützliche Informationen zu C: stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c

    – Chris

    23. Juli 2012 um 23:47 Uhr

Eine spezielle C-Regel besagt, dass es sich bei Funktionsparametern um Array-Typen handelt angepasst zu Zeigertypen. Das bedeutet:

int length(int array[]);

ist äquivalent zu

int length(int *array);

Also, wenn Sie die berechnen sizeof das Array, das Sie tatsächlich die Größe des Zeigers berechnen.

(C99, 6.7.5.3p7) „Eine Deklaration eines Parameters als „Typ-Array“ muss in „qualifizierter Zeiger auf Typ“ angepasst werden, wobei die Typqualifizierer (falls vorhanden) diejenigen sind, die in der angegeben sind [ and ] der Array-Typ-Ableitung.”

  • … und die Folge davon ist, dass Sie nicht umschreiben können length() wie gewünscht funktionieren – wenn eine Funktion die Größe eines Arrays kennen muss, muss sie dieser Funktion als separater Parameter übergeben werden.

    – Café

    24. Juli 2012 um 0:16 Uhr

  • @caf da stimme ich dir zu. Für zusätzliche Informationen ist es sinnvoll, dies auf diese Weise zu tun, insbesondere bei einem ARM-Prozessor mit r0, r1, r2, r3 32-Bit-Registern. Daher kann ein Zeiger in r0 übergeben werden, anstatt Stack verwenden zu müssen.

    Benutzer6754053

    17. Oktober 2016 um 23:29 Uhr

Das Array zerfällt in einen Zeiger, wenn Sie es an eine Funktion übergeben.

Benutzer-Avatar
David Yaw

Wie die anderen Antwortenden angemerkt haben, wird eine Funktion, die für die Annahme eines Arrays deklariert ist, genauso kompiliert, als ob sie einen Zeiger annehmen würde.

Die häufigste Methode, die ich gesehen habe, um Ihre length-Methode auszuführen, ist mit einem #define, aber wenn Sie mit Templates Streiche spielen, können Sie Ihre Funktion zum Laufen bringen.

template <size_t _Size> inline int length(int(& array)[_Size])
{
    //return sizeof(array) / sizeof(int);
    return _Size;
};

int array[] = {1, 2, 3, 4};
printf("%d\n", length(array)); // print 4

Mit Ihrem Array der Länge 4 wird dies als eine Methode kompiliert, die ein Array der Länge 4 akzeptiert und eine statische 4 zurückgibt. Dies hat auch den Vorteil, dass der Compiler nachgibt, wenn Sie versuchen, etwas zu übergeben, das kein Array ist ein Fehler, während die Methode #define dies nicht tut.

int* foo = array;
printf("%d\n", length(foo)); 
    // error C2784: 'int length(int (&)[_Size])' : could not deduce template
    //     argument for 'int (&)[_Size]' from 'int *'
    // test.cpp(56) : see declaration of 'length'

  • Ah, ganz richtig. Na ja, vielleicht findet er es trotzdem nützlich.

    – David Yaw

    24. Juli 2012 um 5:02 Uhr

Benutzer-Avatar
Ted Hopp

Im Hauptprogramm kennt der Compiler die Länge des Arrays. Im Unterprogramm nicht. Insbesondere in einer Unterroutine ein Parameter vom Typ int[] ist identisch mit einem Parameter vom Typ int *. Im Hauptprogramm dagegen array Typ hat int[4]. (Sie können dies testen, indem Sie versuchen, einen anderen Wert zuzuweisen array Innerhalb main. Der Compiler wird sich beschweren.)

Falls Sie es wollen length Um sich der wahren Größe des übergebenen Arrays bewusst zu sein, müssen diese Informationen übergeben werden, wie jeder sagt. Es ist jedoch möglich, einen Verweis auf das Array mit den ebenfalls integrierten Informationen zu erhalten:

int length(int n, int (* array)[n])
{
     return sizeof(*array) / sizeof(int);
}

int main()
{
    int array[] = {1, 2, 3, 4};
    printf("%d\n", length(4, &array)); // print 1
    printf("%d\n", sizeof(array) / sizeof(int)); // print 4
}

Ich weiß allerdings nicht, was dir das eigentlich nützt, da die Größe ja schon vorgegeben ist. Aber Sie sehen, dass die sizeof Operator funktioniert in diesem Fall wie gewünscht.

C speichert keine Laufzeitmetadaten über die Größe eines Arrays mit der Variablen. Irgendwo musst du das selbst hinterlegen.

Eine Variable vom Typ int[] im Rahmen Ihrer Methode Länge ist nur ein Zeiger auf einen Speicherblock. Aus diesem Grund ist die Größe die gleiche wie die Größe jedes anderen Zeigers auf Ihrem System.

Wann Größe von hat zur Kompilierzeit Zugriff auf das Array (wie in Ihrer hauptsächlich Funktion) gibt es stattdessen die Anzahl der vom Array belegten Bytes zurück.

Benutzer-Avatar
AlexDev

Weil die innere Länge des variablen Arrays nicht die gleiche ist wie die äußere. Sie müssen sizeof(array) / sizeof(int) in der Hauptfunktion beibehalten.

1217210cookie-checkWarum ist sizeof(param_array) die Größe des Zeigers?

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

Privacy policy