2009-11-04 7 views

Antwort

19

Array-Größen müssen mit ANSI 89 C bekannt sein. Die Version 99 der Spezifikation hat diese Einschränkung aufgehoben und für Arrays mit variabler Größe zugelassen.

Hier ist die Dokumentation nicht die GNU-Version dieser Funktion

+0

Oh ich sehe. Danke. also alle Elemente des Arrays immer noch auf dem Stack? – root

+0

Ja, das sind sie. Wenn das schlecht ist, benutze malloc wie in anderen Antworten vorgeschlagen. –

4

Wenn Sie ein Array mit dynamischen Größe zuzuweisen, müssen Sie es aus dem Haufen zu bekommen, mit malloc().

+2

Wenn Sie den '(int *)' Cast ablegen, generiert der Compiler einen Fehler, wenn Sie vergessen, die Datei mit dem Namen 'malloc' einzufügen. Daher ist es am besten, die Besetzung nicht mit aufzunehmen. –

+1

'int * a = malloc (s * sizeof * a)' – AnT

0

Sie sind verwirrend zwei Dinge hier.

1), um die Größe eines bereits zugeteilten Array Bestimmen (die Ihr Titel impliziert): divide sizeof() für die gesamten von der Größe von einem (beispielsweise das erste Element):

sizeof(a)/sizeof(a[0]) 

2) dynamisches Zuweisen Speicher als Ihre Frage fragt:

int *a = (int*)malloc(s * sizeof(int)); 
+0

sizeof (a)/sizeof (a [0]) bestimmt die Größe eines Arrays zur Kompilierzeit, nicht zur Laufzeit, wenn es wie eine Array-Deklaration auf dem Stack zugewiesen wird. –

1

Dieser Code wird von C99 Sprachspezifikation unterstützt. Dieser Code wird auch vom GCC-Compiler im C89/90-Modus als Erweiterung unterstützt.

Also, die Antwort auf Ihre Frage (warum es "funktioniert") hängt davon ab, wie Sie es kompilieren. Im Allgemeinen wird dies nicht einmal von einem C89/90-Compiler kompiliert.

0

Es ist wichtig zu verstehen, wie Speicher von einem Compiler zur Variablen zugewiesen wird, um die richtige Antwort auf Ihre Frage zu geben. Es gibt zwei Modi, in denen der Speicher einer Variablen zugewiesen wird, sie kann sich auf einem Heap befinden oder auf einem Stapel liegen. Speicher auf einem Heap wird dynamisch zugewiesen. Eine Variable, die Speicher auf einem Heap zugewiesen ist, kann daher während der Laufzeit ihre Größe erhalten.

Die Arrays im Fall von C sind Speicher auf einem Stapel gegeben. Zum Bereitstellen von Speicher auf einem Stapel sollte die Größe des Speichers dem Compiler während der Kompilierungszeit bekannt sein. So dass während der Laufzeit so viel Speicher für die Variable auf dem Stapel reserviert werden kann. Das ist der Grund, warum Sie die Größe des Arrays zur Laufzeit nicht entscheiden können, was die C-Sprache betrifft.

+1

Das Zuordnen von Speicher auf dem Stapel ist einfach eine Frage des Anpassens des Stapelzeigers - und es gibt keinen grundlegenden Grund, warum der Stapelzeiger nur durch zur Kompilierungszeit bekannte Werte angepasst werden kann. Tatsächlich erlaubt der neueste C-Standard automatische Variablen, deren Größen zur Laufzeit bestimmt werden, und es gibt auch eine gemeinsame Erweiterung 'alloca()', die für Jahre vor dem * das Gleiche lieferte. – caf

0

Variable Length Arrays waren Teil der C-Sprache seit C99. Sie wurden jedoch als ein Merkmal in C11 gemacht - was bedeutet, dass eine C11-konforme Implementierung es nicht bereitstellen muss (obwohl praktisch alle Implementierungen, die C99 unterstützen, sicherlich VLAs in C11 bereitstellen).

Sie können überprüfen, ob Ihre Implementierung keine VLAs mit dem Makro __STDC_NO_VLA__ bereitstellt (wenn es im Kompatibilitätsmodus C99 oder C11 definiert ist, unterstützt Ihre Implementierung keine VLAs).

So eine Array Größe zur Laufzeit möglich ist, in der modernen C (> = C99) und Code wie unten Entscheidung ist in Ordnung:

int s; 
printf("Enter the array size: "); 
scanf("%d", &s); 
int a[s]; 

Ein offensichtlicher Nachteil VLAs ist, dass, wenn s recht groß ist und die Zuweisung von a coud fail. Schlimmer noch, es gibt keine Möglichkeit zu überprüfen, ob die Zuweisung fehlgeschlagen ist und Sie Laufzeitfehler (z. B. segfault) auftreten. Es ist im Wesentlichen undefined behaviour. So möchten Sie VLAs vermeiden, wenn die Array-Größe zu groß ist. Grundsätzlich, im Zweifel, gehen Sie für dynamische Speicherzuweisung (siehe unten).

Ein anderes Problem, viel weniger schwerwiegend im Vergleich zu anderen, mit VLAs ist, dass sie automatische Speicherdauer (aka "Stapel zugeordnet") haben. Also, wenn Sie etwas wollen, das für längere Dauer dauert, dann die Block Scope wo die VLA erklärt wird, dann sind VLAs keine Hilfe.

In C89 gibt es kein VLA. Daher ist die Verwendung der dynamischen Speicherzuweisung der einzige Weg. Obwohl es einige nicht-standardmäßige Erweiterungen gab, wie alloca(), die VLA ähnlich ist und die gleichen Nachteile wie VLAs aufweist).

int s; 
printf("enter the array size: "); 
scanf("%d",&s); 
int *a = malloc(s * sizeof *a); 
... 
free(a);