Sonntag, Dezember 15, 2019

C: bei der Initialisierung eines dynamischen Arrays innerhalb einer Struktur

Bin ich zu versuchen, meine eigenen basic-version der matrix-Multiplikation in C und basierend auf einem anderen Umsetzung, ich habe einen matrix-Datentyp. Der code funktioniert, aber ein C-Anfänger, ich verstehe nicht, warum.

Das Problem: Die habe ich ein struct mit einem dynamischen array drin und ich bin der Initialisierung der Zeiger. Siehe unten:

//Matrix data type
typedef struct
{
    int rows, columns;      //Number of rows and columns in the matrix
    double *array;          //Matrix elements as a 1-D array
} matrix_t, *matrix;

//Create a new matrix with specified number of rows and columns
//The matrix itself is still empty, however
matrix new_matrix(int rows, int columns)
{
    matrix M = malloc(sizeof(matrix_t) + sizeof(double) * rows * columns);
    M->rows = rows;
    M->columns = columns;
    M->array = (double*)(M+1); //INITIALIZE POINTER
    return M;
}

Warum muss ich das array initialisiert werden (double*)(M+1)? Es scheint, dass auch (double*)(M+100) funktioniert ok, aber z.B. (double *)(M+10000) funktioniert nicht mehr, wenn ich meine matrix-Multiplikation Funktion.

  • Bitte: deklarieren Sie nicht zwei Arten in einem typedef verstecken sich nicht ein Zeiger-Typ in einem typedef, nicht mit Namen mit _t, Sie sind reserviert von POSIX, und verwenden Sie size_t für rows und colums.
  • Nein, _t ist nicht reserviert für POSIX. Es ist eigentlich nicht reserviert für irgendwas. Obwohl, man sollte es nur verwenden, die in Typ-Namen. size_t ist nicht POSIX-zum Beispiel.
InformationsquelleAutor Zni | 2013-09-06

3 Kommentare

  1. 2

    M+1 Punkte auf den Speicher, der sofort folgt M (d.h. nach den zwei int und die double*). Dies ist der Speicher, den Sie haben, reserviert für die matrix-Daten:

    matrix M = malloc(sizeof(matrix_t) + sizeof(double) * rows * columns);
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    Mit M+100 oder M+10000 und dann versuchen, füllen die matrix wird in Folge Undefiniertes Verhalten. Dies könnte dazu führen, dass ein Programm abstürzt oder ein Programm, die zu funktionieren scheint (aber in Wirklichkeit defekt ist), oder irgendetwas dazwischen.

  2. 3

    Ist die empfohlene Methode für diese Art von Sachen ist ohne Größenangabe-array in Verbindung mit offsetof. Es sorgt für die richtige Ausrichtung.

    #include <stddef.h>
    #include <stdlib.h>
    
    //Matrix data type
    typedef struct s_matrix
    {
        int rows, columns;      //Number of rows and columns in the matrix
        double array[];         //Matrix elements as a 1-D array
    } matrix;
    
    //Create a new matrix with specified number of rows and columns
    //The matrix itself is still empty, however
    matrix* new_matrix(int rows, int columns)
    {
        size_t size = offsetof(matrix_t, array) + sizeof(double) * rows * columns;
        matrix* M = malloc(size);
        M->rows = rows;
        M->columns = columns;
        return M;
    }
    • Vielen Dank für diese, ich Stimme zu, dass es mehr Sinn macht, nicht zu verbergen, ein Zeiger-Typ typdef, wie bereits von Jens. Ich denke aber, die Sie aufnehmen möchten, offsetof(matrix, array), da matrix_t ist nicht definiert in deinem code…
    • Was ist der richtige Weg, um Daten in das array? Meine alten Methoden, die ich verwendet habe mit der ersten version des Codes nicht mehr funktionieren. Ich bekomme nur „Fehler: invalid use of flexible array member“, was auch immer ich versuche.
    • Oh, diese einfache Sache scheint zu funktionieren. Allerdings habe ich Probleme mit dem einstellen aller Werte des Arrays simulataneously. Zuvor schrieb ich matrix* A = new_matrix(3, 2); double amatrix[] = { 3, 2, 8, 1, 9, 2 }; A->array = amatrix; aber das funktioniert nicht mehr.
    • Dieser code füllt nicht das array, wird es benutzt, um den Zeiger (alle Speicher, den Sie zugewiesen gleich nach der Struktur nutzlos). Kopieren Sie den Inhalt eines Arrays mit memcpy().
    • Noch einmal vielen Dank!
  3. 0

    Müssen Sie es initialisieren, da sonst (denn es warten) es ist nicht initialisierte!

    Und Sie nicht verwenden können, einen nicht initialisierten Zeiger für nichts, außer zu generieren Undefiniertes Verhalten.

    Initialisieren zu M + 1 ist genau richtig und sehr guten code. Jeder andere Wert nicht den Speicher verwenden, der Sie zugeordnet, die für genau diesen Zweck.

    Mein Punkt ist, dass die double * am Ende der Struktur wird nicht „automatisch“ Punkt, an diese Erinnerung, das ist die implizite überzeugung, die in Ihrer Frage, warum sollte es initialisiert werden. Also, es muss auf die richtige Adresse.

Kostenlose Online-Tests

Letzte Fragen

Tun ItemView löst Blase?

Ich habe eine CompositeView für eine Tabelle. Ich habe Trigger-set in der Kind-ItemView für jede Zeile... var TableRow = Marionette.ItemView.extend({ tagName:...

Wie kann ich untersuchen, WCF was 400 bad request über GET?

Die folgenden WCF-endpoint funktioniert gut mit dem WCF test client: AssetList ListFlaggedAssets(short processCode, string platform, string endpoint = "null", string portalId = "null", int...

Bei der Verwendung von UUIDs, sollte ich auch mit AUTO_INCREMENT?

Wir bauen eine neue web-app, die eine offline-iPad - /Android-app-version auf einer Reihe von lokalen Geräten, die Einsätze mit neuen Daten. Als solche benötigen...

Actionscript-Objekt, das verschiedene Eigenschaften

Wie kann ich die Anzahl der Eigenschaften in einer generischen Actionscript-Objekt? (Wie die Array-Länge) InformationsquelleAutor Fragsworth | 2011-01-15

Wie plot mehrere Graphen und nutzen Sie die Navigations-Taste im [matplotlib]

Die neueste version von matplotlib erstellt automatisch Navigations-buttons unter den graph. Aber die Beispiele, die ich finden alles im Internet zeigen, wie erstellen Sie...