3 Stimmen

Bitte übersetzen Sie dies, indem Sie dieselben HTML-Tags beibehalten, falls vorhanden: C kopiere 3-dimensionales Array

Ich habe einen Zeiger auf ein 3-dimensionales Array, wie folgt:

char ***_cube3d

Und ich initialisiere es so:

_cube3d = (char ***)malloc(size * (sizeof(char**)));
for (int i = 0; i< size; i++) {
    _cube3d[i] = (char **)malloc(size * sizeof(char*));
    for (int j = 0; j

`

Beachten Sie, dass das Array dynamischer Größe ist und Tausende von Elementen enthalten kann, daher können wir es nicht im Voraus als Array deklarieren.

Jetzt möchte ich alle seine Inhalte so effizient wie möglich in ein anderes Array kopieren. Ich kenne die Lösung mit verschachtelter Schleife, bei der wir jedes Element einzeln kopieren, jedoch scheint sie mir extrem ineffizient. Gibt es eine Möglichkeit, diesen Vorgang zu beschleunigen? C++-Code ist willkommen, obwohl ich es lieber in reinem C hätte, da ich vorhabe, diese Lösung in Objective C zu überführen, und ich C++-Code in einem sauberen Objective-C-Projekt vermeiden möchte.

Kann mir jemand in die richtige Richtung weisen?

`

3voto

RamblingMad Punkte 5184

Verwenden Sie das, was Sie bereits haben (aber das erste malloc mit sizeof(char***) korrigieren)

Sie könnten das Array kopieren, indem Sie eine Reihe von for-Schleifen wie diese ausführen:

char new_cube[side][side][side];
for(unsigned int x = 0; x < side; x++)
    for(unsigned int y = 0; y < side; y++)
        for(unsigned int z = 0; z < side; z++)
            new_cube[x][y][z] = old_cube[x][y][z];

ODER:

char new_cube[side][side][side];
for(unsigned int x = 0; x < side; x++)
    for(unsigned int y = 0; y < side; y++)
        memcpy(new_cude[x][y], old_cube[x][y], sizeof(char)*side);

was etwas schneller sein könnte.

Wenn Sie diese Methode verwenden, vermeiden Sie die Verwendung von C++ (wie Sie gesagt haben) und Ihre Code-Komplexität bleibt minimal.

2voto

jxh Punkte 66464

Wenn Sie C.99 verwenden, können Sie ein Array mit variabler Länge (VLA) verwenden, um Ihr 3-dimensionales Array dynamisch zuzuweisen. Sobald side festgelegt ist, können Sie Ihren Zeiger wie folgt deklarieren:

char (*cube3d_)[side][side];

Und initialisieren Sie es dann so:

cube3d_ = malloc(side * sizeof(*cube3d_));

Beachten Sie, dass Sie in C nicht verpflichtet sind, den Rückgabewert von malloc() zu casten, und dies im schlimmsten Fall zu einem undefinierten Verhalten führen kann. Da der "Würfel" als zusammenhängender Block allokiert wurde, kann er mit memcpy() kopiert werden.

C++ hat keine VLA. Sie können einen vector verwenden, um das C++-Äquivalent Ihrer mehrdimensionalen dynamischen Allokationsstruktur zu erhalten:

std::vector > >
cube3d_(side, std::vector >(side, std::vector(side)));

Sie können es dann mit einem Kopierkonstruktor oder einer Zuweisung kopieren.


Wenn cube3d_ eine Membervariable eines Objekts/ einer Struktur ist, solange Ihr Objekt den Wert von side kennt, können Sie weiterhin einen VLA-Zeiger verwenden, um auf den Speicher zuzugreifen. Zum Beispiel:

struct Obj {
    size_t side_;
    void *cube3d_;
};

//...
size_t side = 3;

//...
Obj o;
o.side_ = side;
char (*p)[o.side_][o.side_] = malloc(o.side_ * sizeof(*p));
o.cube3d_ = p;

//...
char (*q)[o.side_][o.side_] = o.cube3d_;
q[1][2][2] = 'a';

1voto

Richard Chambers Punkte 15587

Hier ist ein Ansatz unter Verwendung von C und structs, um etwas in Richtung objektorientierter Programmierung zu bieten, zusammen mit einer Reihe von Hilfsfunktionen.

Die Idee hier war es, Kerricks Vorschlag eines zusammenhängenden Arrays zu verwenden.

Ich bin mir nicht sicher, ob ich die Offset-Berechnung korrekt habe und es wurde nicht getestet, daher ist es das wert, was du bezahlst. Es könnte jedoch als Ausgangspunkt hilfreich sein.

Die Idee ist, einen einzigen zusammenhängenden Speicherbereich zu haben, um die Speicherverwaltung einfacher zu gestalten. Und eine Funktion zu verwenden, um auf ein bestimmtes Element mit einem nullbasierten Offset in x-, y- und z-Richtung zuzugreifen. Da ich mir nicht sicher war, welcher Elementgröße/-typ, habe ich auch dies zu einer Variable gemacht.

#include 

typedef struct _Array3d {
    int   elSize;     // Größe jedes Elements des Arrays in Bytes
    int   side;       // Länge jeder Seite des 3D-Würfels in Elementen
    char  * (*Access) (struct _Array3d *pObj, int x, int y, int z);
    char  buffer[1];
} Array3d;

static char * Array3d_Access (Array3d *pObj, int x, int y, int z)
{
    char *pBuf = NULL;

    if (pObj && x < pObj->side && y < pObj->side && z < pObj->side) {
        pBuf = &(pObj->buffer[x * pObj->side * pObj->elSize * pObj->side * pObj->elSize + y * pObj->side * pObj->elSize + z * pObj->elSize]);
    }

    return pBuf;
}

// Erstellt einen Array3d-Würfel, indem die Länge jeder Seite zusammen mit der Größe jedes Elements angegeben wird.
Array3d *Array3d_Factory (int side, int elSize)
{
    Array3d *pBuffer = malloc (sizeof(Array3d) + side * elSize * side * elSize * side * elSize);

    if (pBuffer) {
        pBuffer->elSize = elSize;
        pBuffer->side = side;
        pBuffer->Access = Array3d_Access;
    }

    return pBuffer;
}

// Erstellt einen Array3d-Würfel, der die gleiche Größe wie ein vorhandener Array3d-Würfel hat.
Array3d *Array3d_FactoryObj (Array3d *pObj)
{
    Array3d *pBuffer = NULL;

    if (pObj) {
        int iBufferSize = pObj->side * pObj->elSize * pObj->side * pObj->elSize * pObj->side * pObj->elSize;

        pBuffer = malloc (sizeof(Array3d) + iBufferSize);
        if (pBuffer) {
            pBuffer->elSize = pObj->elSize;
            pBuffer->side = pObj->side;
            pBuffer->Access = pObj->Access;
        }
    }

    return pBuffer;
}

// Dupliziert oder klonen Sie einen vorhandenen Array3d-Würfel in einen neuen.
// Gibt NULL zurück, wenn das Klone nicht erfolgt ist.
Array3d *Array3d_Dup (Array3d *pObjDest, Array3d *pObjSrc)
{
    if (pObjSrc && pObjDest && pObjSrc->elSize == pObjDest->elSize && pObjSrc->side == pObjDest->side) {
        int iBufferSize = pObjSrc->side * pObjSrc->elSize * pObjSrc->side * pObjSrc->elSize * pObjSrc->side * pObjSrc->elSize;

        memcpy (pObjDest->buffer, pObjSrc->buffer, iBufferSize);
    } else {
        pObjDest = NULL;
    }

    return pObjDest;
}

int main(int argc, _TCHAR* argv[])
{
    Array3d *pObj = Array3d_Factory(10, 20 * sizeof(char));

    char *pChar = pObj->Access(pObj, 1, 2, 3);
    return 0;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X