Wie erstelle ich ein Array, ohne die Größe in C anzugeben?

Lesezeit: 6 Minuten

Ich versuche, ein Int- und ein Float-Array ohne Größe zu erstellen (es könnte 0 sein oder es könnte inkrementieren, während der Benutzer das Programm verwendet).

Ich habe versucht, Folgendes zu tun:

int bills[];

float totalAmount[];

Ich kann keine maximale Größe zuweisen, da ich jedes Array mit einer for-Schleife drucke (wenn ich eine Größe von 99 zuweise, drucke ich 99 Zeilen, und das möchte ich nicht).

  • Sie müssen Speicher dynamisch zuweisen, wenn Sie nicht wissen, wie viel Speicherplatz Sie benötigen. Einblick in malloc() Und free() Dokumentation.

    – Tanveer Badar

    29. April 2018 um 5:45 Uhr

  • Sie können das einfach nicht in C tun, es gibt jedoch viele alternative Lösungen, aber ich glaube nicht, dass wir Ihnen mehr helfen können als ein gutes Buch von C. Als Anfänger sollten Sie sich eine einfache Lösung ansehen malloc() Und realloc()

    – Sternengatter

    29. April 2018 um 5:45 Uhr

  • Wenn die maximale Größe bekannt (und klein) ist, könnten Sie verwenden int bills[99]; und dann die Anzahl der verwendeten Artikel separat verfolgen. Du Wille müssen sowieso die Anzahl der Rechnungen im Auge behalten.

    – Bo Persson

    29. April 2018 um 11:53 Uhr


Benutzeravatar von chqrlie
chqrlie

C unterstützt keine Arrays mit einer dynamischen Anzahl von Elementen. Die Anzahl der Elemente eines Arrays muss entweder zur Kompilierzeit bestimmt werden oder da C99 zur Laufzeit zum Zeitpunkt der Erstellung ausgewertet werden kann. Nachdem das Array erstellt wurde, ist seine Größe festgelegt und kann nicht geändert werden. Es gibt einige Fälle, in denen die Größe zwischen den nicht explizit angegeben ist []entweder in Array-Definitionen oder in Array-Deklarationen.

Du kannst definieren ein Array ohne explizite Größe für die ganz linke Dimension, wenn Sie einen Initialisierer bereitstellen. Der Compiler leitet die Größe vom Initialisierer ab:

int a[] = { 1, 2, 3 };              // equivalent to int a[3] = { 1, 2, 3 };
int m[][2] = {{ 1, 2 }, { 3, 4 }};  // equivalent to int m[2][2] = {{ 1, 2 }, { 3, 4 }};
char s[] = "Hello world\n";         // equivalent to char s[13] = "Hello world\n";

Beachten Sie, wie der Compiler das implizite Null-Terminator im String-Case hinzufügt.

Du kannst erklären ein Array ohne Größenbezeichner für die ganz linke Dimension in mehreren Fällen:

  • als globale Variable mit extern Klassenspeicher (das Array ist an anderer Stelle definiert),
  • als Funktionsparameter: int main(int argc, char *argv[]). In diesem Fall wird die für die ganz linke Dimension angegebene Größe ohnehin ignoriert.
  • als letztes Mitglied einer struct mit mehr als einem benannten Mitglied. Dies ist eine C99-Erweiterung namens a flexible Anordnung.

Der Compiler hat keine Informationen über die tatsächliche Größe dieser Arrays. Der Programmierer verwendet einige andere Informationen, um die Länge zu bestimmen, entweder aus einer separaten Variablen oder aus dem Array-Inhalt.

Im Fall eines Funktionsarguments wird das Array als Zeiger übergeben und selbst wenn die Anzahl der Elemente angegeben ist, sizeof(argv) wertet die Größe eines Zeigers aus.

  • Wissen Sie, ob die Fälle, in denen Sie ein Array ohne Größenangabe für die Dimension ganz links deklarieren können, in C++ dieselben sind (offensichtlich “struct” müsste wahrscheinlich geändert werden in “struct oder class” )? Ich habe den Funktionsparameterfall ausprobiert; es scheint, als wäre die Syntax gültig, aber die Variable wird zu einem Zeiger (gemäß typeid(the_variable).name).

    – Hallo Auf Wiedersehen

    18. Oktober 2020 um 20:11 Uhr

  • Es könnte auch erwähnt werden, dass nur C99-Flexible-Arrays zugelassen sind structs mit mindestens zwei benannten Mitgliedern.

    – Hallo Auf Wiedersehen

    18. Oktober 2020 um 20:34 Uhr

  • @HelloGoodbye: guter Punkt über mehr als ein benanntes Mitglied … Antwort geändert.

    – chqrlie

    19. Januar 2021 um 1:49 Uhr


  • @HelloGoodbye: Arrays werden immer als Zeiger auf ihr erstes Element übergeben.

    – chqrlie

    19. Januar 2021 um 1:50 Uhr

  • “Arrays werden immer als Zeiger auf ihr erstes Element übergeben” – in C, aber in diesem Fall nicht in C++, richtig? Ich glaube, ein Array mit einem Größenbezeichner in C++ ist ein eigener Datentyp. Oder meinen Sie, dass der Datentyp in einen Zeiger geändert wird, wenn Sie ihn als Funktionsparameter verwenden?

    – Hallo Auf Wiedersehen

    20. Januar 2021 um 2:07 Uhr

Benutzeravatar von Edwin Buck
Edwin Buck

Sie deklarieren kein Array ohne Größe, sondern einen Zeiger auf eine Reihe von Datensätzen.

also, wenn du wolltest

int bills[];

Der richtige Weg, dies in C zu tun, ist

int* bills;

Und Sie müssen irgendwann die Größe zuweisen und das Array initialisieren.

bills = (int*)malloc(sizeof(int)*items);

Dasselbe gilt für Arrays anderer Datentypen. Wenn Sie die Größe des Arrays erst zur Laufzeit kennen, sollten Sie Zeiger auf Speicher verwenden, denen zur Laufzeit die richtige Größe zugewiesen wird.

  • Wirke ich die Rückkehr von Malloc?

    – Sternengatter

    29. April 2018 um 6:16 Uhr

  • @EdwinBuck Ich habe deinen Kommentar nicht gut verstanden, ich bin kein englischer Muttersprachler. Tut mir leid, wenn Sie das Gefühl haben, dass ich Sie persönlich angreife. Ich denke, dass jedes Argument über “alte Compiler könnte” keinen Sinn macht, wenn wir uns im Jahr 2018 befinden. Ich denke, Sie haben das Problem unterschätzt, wenn Sie einen falschen Zeigertyp verwenden. Ich denke, jeder moderne C-Code sollte verwenden bills = malloc(sizeof *bills * items); und dieser alte Programmierer sollte mit seiner alten schlechten Angewohnheit aufhören. Modernes C möchte ohne altes C leben. Es ist die Erfahrung von 30 Jahren C-Programmierer, die zu dem Schluss kommt, dass es besser war, es so zu schreiben.

    – Sternengatter

    30. April 2018 um 13:06 Uhr

Benutzeravatar von J...S
J…S

Sie könnten eine Kombination aus verwenden malloc() (oder calloc()), realloc() Und free() um das zu erreichen.

Speicher kann als Blöcke fester Größe zugewiesen werden, anstatt Speicher für jede zu speichernde Zahl neu zuzuweisen.

Lassen Sie uns ein Makro (oder eine const wenn du möchtest) BLOCK_SIZE.

#define BLOCK_SIZE 10

Deklarieren Sie zuerst einen Zeiger des geeigneten Typs und weisen Sie den ersten Block zu.

Beachten Sie, dass malloc() ebenso gut wie realloc() zurückkehren NULL wenn ein Fehler aufgrund von Gründen wie unzureichendem Speicher aufgetreten ist.

int *ptr=malloc(sizeof(int)*BLOCK_SIZE);    
if(ptr==NULL)
{
    perror("some error");
    return 1;
}

Deklarieren Sie nun eine Variable, um den maximal möglichen Index gemäß dem aktuell zugewiesenen Speicher zu speichern (um illegalen Speicherzugriff zu vermeiden).

int max_index = BLOCK_SIZE-1;

Verwenden Sie jetzt eine Schleife.

for(int i=0; ; ++i)
{
    if(i > max_index)
    {
        ptr=realloc(ptr, (max_index+1 + BLOCK_SIZE)*sizeof(int));
        if(ptr == NULL)
        {
            perror("insufficient memory!");
            break;
        }
        printf("\nRealloced!");
        max_index += BLOCK_SIZE;
    }
    scanf("%d", &ptr[i]);
    printf("\n%d: %d", i, ptr[i]);
}

In jeder Iteration prüfen wir, ob i ist größer als max_index. Wenn dies der Fall ist, wird ein weiterer Block mit zugewiesen realloc() bevor Sie den Wert ablesen.

Vergessen Sie nicht, den Speicher freizugeben, wenn Sie ihn nicht mehr verwenden.

free(ptr);

Außerdem, wie in diesem Beitrag besprochen, malloc() ist praktisch dasselbe wie realloc() mit dessen erstem Argument NULL.

Und in dem von Ihnen geposteten Code muss der Rückgabewert von nicht explizit umgewandelt werden calloc() denn was zurückgegeben wird ist a void Zeiger, der implizit in den Zielzeigertyp konvertiert würde.

Siehe dies und das.

Ich denke, Sie können ihm eine maximale Größe geben. Wenn Sie nur die ersten paar Elemente anzeigen möchten, können Sie eine For-Schleife nur bis zu diesem Element setzen. Dasselbe gilt für die Eingabe, wenn Sie die ersten 30 Elemente initialisieren möchten, setzen Sie eine For-Schleife bis zu 30.

1444040cookie-checkWie erstelle ich ein Array, ohne die Größe in C anzugeben?

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

Privacy policy