2010-06-01 5 views
26

Komplettes Beispiel:Warum hat ein C-Array einen falschen Wert für sizeof(), wenn es an eine Funktion übergeben wird?

#include <stdio.h> 

void test(int arr[]) { 
    int arrSize = (int)(sizeof(arr)/sizeof(arr[0])); 
    printf("%d\n", arrSize); // 2 (wrong?!) 
} 

int main (int argc, const char * argv[]) { 
    int point[3] = {50, 30, 12}; 

    int arrSize = (int)(sizeof(point)/sizeof(point[0])); 
    printf("%d\n", arrSize); // 3 (correct :-)) 

    test(point); 

    return 0; 
} 

Bevor es an eine Funktion, sizeof gibt mir den richtigen Wert. Wenn Sie genau dasselbe auf dem gleichen Array in der Funktion tun, erhalten Sie seltsame Ergebnisse. Es fehlt ein Element. Warum?

Antwort

37

Wenn Sie ein Array in eine Funktion in C übergeben, verfällt das Array in einen Zeiger auf sein erstes Element. Wenn Sie sizeof für den Parameter verwenden, nehmen Sie die Größe des Zeigers, nicht das Array selbst.

Wenn Sie die Funktion benötigen, die Größe des Arrays zu kennen, sollten Sie es als separate Parameter übergeben:

void test(int arr[], size_t elems) { 
    /* ... */ 
} 

int main(int argc, const char * argv[]) { 
    int point[3] = {50, 30, 12}; 
    /* ... */ 
    test(point, sizeof(point)/sizeof(point[0])); 
    /* ... */ 
} 

auch zur Kenntnis, dass aus einem ähnlichen Grunde (die sizeof einen Zeiger nehmen), das sizeof(point)/sizeof(point[0]) Trick funktioniert nicht für ein dynamisch zugewiesenes Array, nur ein Array auf dem Stapel zugeordnet.

2

Weil, wenn es übergeben wird, nur der Zeiger auf Array tatsächlich übergeben wird.

Ihre Frage wird auch unter The C Programming FAQ beantwortet. Frage 6.21.

+0

Wählerisch sein: Es ist ein Zeiger auf das erste Element des Arrays, das übergeben wird. Gleicher Wert, aber anderer Typ. – alk

0

Da sizeof() nicht die Größe eines Arrays in C sagt. Es tut etwas ganz anderes.

sizeof C++ reference

+0

Wenn Sie sich das Beispiel genau angesehen haben, würden Sie sehen, dass ich sizeof nicht verwende, um die Anzahl der Elemente im Array direkt zu ermitteln ... sizeof sollte mir sagen, wie viel Speicher für das Array reserviert ist ... und eigentlich sollte das mit der Anzahl der Elemente übereinstimmen, wenn die Größe eines Elements bekannt ist. oder verpasse ich etwas? – dontWatchMyProfile

+0

Ich stehe korrigiert. Aber wie oben erwähnt, sei vorsichtig mit Zeigern.Sie sagen Ihnen ihre Größe, nicht die Größe des Typs, auf den Sie zeigen. – PeterK

12

Da Array decayed auf einen Zeiger, wenn die Funktion als Argument übergeben, so sizeof gibt man 4 und 8 für 32-Bit- und 64-Bit-Plattformen sind.

6

Außerdem ist es wichtig zu verstehen, dass sizeof bei kompiliert Zeit ausgewertet wird. Da dies der Fall ist, ist es nicht sinnvoll, eine andere Ausgabe in test() zu erwarten, abhängig davon, was übergeben wurde. Die sizeof Berechnung wurde durchgeführt, als die Funktion kompiliert wurde.

2

Da in C, C++ und Objective-C Funktionen nicht tatsächlich Array-Parameter haben können. Sie können nur Parameter haben, die wie Array-Parameter aussehen, aber sie sind nicht. In Ihrem Beispiel

void test(int arr[]) 

die Compiler sieht „es ist ein Parameter, wie ein Array von int sieht“, und ersetzt diese Parameter mit einem „Zeiger auf int“. So ist die Funktion, die Sie geschrieben hat, ist absolut, zu hundert Prozent identisch mit

void test (int* arr) 

Daher innerhalb der Funktion sizeof (arr) gibt Ihnen die Größe eines „Zeiger auf int“.