Übergeben eines 2D-Arrays an eine C ++ - Funktion

324

Ich habe eine Funktion, die ich als Parameter für ein 2D-Array mit variabler Größe verwenden möchte.

Bisher habe ich Folgendes:

void myFunction(double** myArray){
     myArray[x][y] = 5;
     etc...
}

Und ich habe an anderer Stelle in meinem Code ein Array deklariert:

double anArray[10][10];

Ein Anruf myFunction(anArray)gibt mir jedoch einen Fehler.

Ich möchte das Array nicht kopieren, wenn ich es übergebe. Alle vorgenommenen Änderungen myFunctionsollten den Status von ändern anArray. Wenn ich das richtig verstehe, möchte ich nur einen Zeiger auf ein 2D-Array als Argument übergeben. Die Funktion muss auch Arrays unterschiedlicher Größe akzeptieren. So zum Beispiel [10][10]und [5][5]. Wie kann ich das machen?

RogerDarwin
quelle
1
Parameter 3 kann nicht von 'double [10] [10]' in 'double **'
konvertiert werden
3
Die akzeptierte Antwort zeigt nur 2 Techniken [seine (2) und (3) sind gleich], aber es gibt 4 einzigartige Möglichkeiten, ein 2D-Array an eine Funktion zu übergeben .
Legends2k
Genau genommen sind sie keine 2D-Arrays, aber diese Konvention (obwohl sie zu UB führt), ein Array von Zeigern zu haben, die jeweils auf ein (1D) Array zeigen, scheint weit verbreitet zu sein :( Ein abgeflachtes 1D-Array von mxn Länge, mit
Hilfsfunktionen
EINFACHSTE - func(int* mat, int r, int c){ for(int i=0; i<r; i++) for(int j=0; j<c; j++) printf("%d ", *(mat+i*c+j)); }. Nennen wir es wieint mat[3][5]; func(mat[0], 3, 5);
Minhas Kamal

Antworten:

413

Es gibt drei Möglichkeiten, ein 2D-Array an eine Funktion zu übergeben:

  1. Der Parameter ist ein 2D-Array

    int array[10][10];
    void passFunc(int a[][10])
    {
        // ...
    }
    passFunc(array);
  2. Der Parameter ist ein Array, das Zeiger enthält

    int *array[10];
    for(int i = 0; i < 10; i++)
        array[i] = new int[10];
    void passFunc(int *a[10]) //Array containing pointers
    {
        // ...
    }
    passFunc(array);
  3. Der Parameter ist ein Zeiger auf einen Zeiger

    int **array;
    array = new int *[10];
    for(int i = 0; i <10; i++)
        array[i] = new int[10];
    void passFunc(int **a)
    {
        // ...
    }
    passFunc(array);
Shengy
quelle
4
@ Overflowh Sie können die Elemente von arraymit bekommen array[i][j]:)
Shengy
14
Für den 1. Fall kann der Parameter als deklariert werden int (*a)[10].
Zachary
9
Für den 2. Fall kann der Parameter als deklariert werden int **.
Zachary
1
@Zack: Du hast recht, es gibt wirklich nur zwei Fälle; einer ist ein Zeiger von Zeiger zu Zeiger und der andere ist ein einzelner Zeiger auf ein ganzzahliges Array der Größe n, d int (*a) [10]. h .
Legends2k
3
Fall 2 und 3 sind keine 2D-Arrays, daher ist diese Antwort irreführend. Sehen Sie das .
Lundin
178

Feste Größe

1. Als Referenz übergeben

template <size_t rows, size_t cols>
void process_2d_array_template(int (&array)[rows][cols])
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

In C ++ ist das Übergeben des Arrays als Referenz ohne Verlust der Dimensionsinformationen wahrscheinlich das sicherste, da man sich keine Sorgen machen muss, dass der Aufrufer eine falsche Dimension übergibt (Compiler-Flags bei Nichtübereinstimmung). Dies ist jedoch mit dynamischen (Freestore-) Arrays nicht möglich. Es funktioniert nur für automatische ( normalerweise stapelweise lebende ) Arrays, dh die Dimensionalität sollte zur Kompilierungszeit bekannt sein.

2. Übergeben Sie den Zeiger

void process_2d_array_pointer(int (*array)[5][10])
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < 5; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << (*array)[i][j] << '\t';
        std::cout << std::endl;
    }    
}

Das C-Äquivalent der vorherigen Methode übergibt das Array per Zeiger. Dies sollte nicht mit der Übergabe des verfallenen Zeigertyps des Arrays verwechselt werden (3) ist die übliche, beliebte Methode, wenn auch weniger sicher als diese, aber flexibler. Verwenden Sie diese Methode wie in (1) , wenn alle Dimensionen des Arrays zur Kompilierungszeit festgelegt und bekannt sind. Beachten Sie, dass beim Aufrufen der Funktion die Adresse des Arrays übergeben werden sollte process_2d_array_pointer(&a)und nicht die Adresse des ersten Elements durch Zerfall process_2d_array_pointer(a).

Variable Größe

Diese werden von C geerbt, sind jedoch weniger sicher. Der Compiler kann dies nicht überprüfen und garantiert, dass der Aufrufer die erforderlichen Dimensionen übergibt. Die Funktion basiert nur auf dem, was der Anrufer als Dimension (en) übergibt. Diese sind flexibler als die oben genannten, da Arrays unterschiedlicher Länge immer an sie übergeben werden können.

Es ist zu beachten, dass es in C kein direktes Übergeben eines Arrays an eine Funktion gibt [während sie in C ++ als Referenz übergeben werden können (1) ]; (2) übergibt einen Zeiger auf das Array und nicht auf das Array selbst. Das Übergeben eines Arrays im Ist-Zustand wird zu einer Zeigerkopieroperation, die durch die Art des Zerfalls des Arrays in einen Zeiger erleichtert wird .

3. Übergeben Sie (Wert) einen Zeiger auf den verfallenen Typ

// int array[][10] is just fancy notation for the same thing
void process_2d_array(int (*array)[10], size_t rows)
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

Obwohl dies int array[][10]zulässig ist, würde ich es nicht über die obige Syntax empfehlen, da die obige Syntax deutlich macht, dass der Bezeichner arrayein einzelner Zeiger auf ein Array mit 10 Ganzzahlen ist, während diese Syntax wie ein 2D-Array aussieht, aber der gleiche Zeiger auf ist ein Array von 10 ganzen Zahlen. Hier kennen wir die Anzahl der Elemente in einer einzelnen Zeile (dh die Spaltengröße, hier 10), aber die Anzahl der Zeilen ist unbekannt und muss daher als Argument übergeben werden. In diesem Fall besteht eine gewisse Sicherheit, da der Compiler markieren kann, wenn ein Zeiger auf ein Array mit einer zweiten Dimension ungleich 10 übergeben wird. Die erste Dimension ist der variierende Teil und kann weggelassen werden. Hier finden Sie die Gründe, warum nur die erste Dimension weggelassen werden darf.

4. Übergeben Sie den Zeiger auf einen Zeiger

// int *array[10] is just fancy notation for the same thing
void process_pointer_2_pointer(int **array, size_t rows, size_t cols)
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

Wieder gibt es eine alternative Syntax int *array[10], die dieselbe ist wie int **array. In dieser Syntax wird das [10]ignoriert, wenn es in einen Zeiger zerfällt, wodurch es wird int **array. Vielleicht ist es nur ein Hinweis für den Aufrufer, dass das übergebene Array mindestens 10 Spalten haben sollte, auch wenn eine Zeilenanzahl erforderlich ist. In jedem Fall kennzeichnet der Compiler keine Längen- / Größenverletzungen (er prüft nur, ob der übergebene Typ ein Zeiger auf Zeiger ist), weshalb hier sowohl Zeilen- als auch Spaltenanzahl als Parameter erforderlich sind.

Hinweis: (4) ist die am wenigsten sichere Option, da kaum eine Typprüfung durchgeführt wird und die unpraktischste ist. Ein 2D-Array kann dieser Funktion nicht legitim übergeben werden. C-FAQ verurteilt die übliche Problemumgehung, int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10);da dies möglicherweise zu undefiniertem Verhalten aufgrund von Array-Abflachung führen kann. Die richtige Art, ein Array in dieser Methode zu übergeben, bringt uns zu dem unbequemen Teil, dh wir benötigen ein zusätzliches (Ersatz-) Array von Zeigern, wobei jedes seiner Elemente auf die jeweilige Zeile des tatsächlich zu übergebenden Arrays zeigt. Dieser Ersatz wird dann an die Funktion übergeben (siehe unten). All dies, um die gleiche Arbeit wie die oben genannten Methoden zu erledigen, die sicherer, sauberer und vielleicht schneller sind.

Hier ist ein Treiberprogramm zum Testen der oben genannten Funktionen:

#include <iostream>

// copy above functions here

int main()
{
    int a[5][10] = { { } };
    process_2d_array_template(a);
    process_2d_array_pointer(&a);    // <-- notice the unusual usage of addressof (&) operator on an array
    process_2d_array(a, 5);
    // works since a's first dimension decays into a pointer thereby becoming int (*)[10]

    int *b[5];  // surrogate
    for (size_t i = 0; i < 5; ++i)
    {
        b[i] = a[i];
    }
    // another popular way to define b: here the 2D arrays dims may be non-const, runtime var
    // int **b = new int*[5];
    // for (size_t i = 0; i < 5; ++i) b[i] = new int[10];
    process_pointer_2_pointer(b, 5, 10);
    // process_2d_array(b, 5);
    // doesn't work since b's first dimension decays into a pointer thereby becoming int**
}
legends2k
quelle
Was ist mit der Übergabe dynamisch zugeordneter Arrays an Funktionen in C ++? Im C11-Standard kann dies für statisch und dynamisch zugewiesene Arrays wie das fn (int col, int row, int array [col] [row]) durchgeführt werden: stackoverflow.com/questions/16004668/… Ich habe die Frage für dieses Problem gestellt : stackoverflow.com/questions/27457076/…
42n4
@ 42n4 Fall 4 behandelt dies (auch für C ++). Für dynamisch zugewiesenen Arrays, nur die Linie innerhalb der Schleife würde von ändern b[i] = a[i];, sagen wir, b[i] = new int[10];. Man kann auch bdynamisch zuweisen int **b = int *[5];und es wird immer noch so funktionieren, wie es ist.
Legends2k
1
Wie funktioniert die Adressierung array[i][j]in der Funktion in 4) ? Weil es ptr zu ptr empfangen hat und den Wert der letzten Dimension nicht kennt, was ist notwendig, um eine Verschiebung für die korrekte Adressierung durchzuführen?
user1234567
2
array[i][j]ist nur eine Zeigerarithmetik, dh zum Wert des Zeigers array, würde es idas Ergebnis addieren und dereferenzieren als int*, zu dem es jdiesen Ort addieren und dereferenzieren würde , indem es einen liest int. Also, nein, es muss keine Dimension dafür kennen. Aber das ist der springende Punkt! Der Compiler nimmt das Wort des Programmierers im Glauben und wenn der Programmierer falsch war, kommt es zu undefiniertem Verhalten. Dies ist der Grund, warum ich erwähnt hatte, dass Fall 4 die am wenigsten sichere Option ist.
Legends2k
In solchen Fällen kann eine Struktur Ihnen gute Dienste leisten.
Xofo
40

Als Modifikation von Shengys erstem Vorschlag können Sie Vorlagen verwenden, damit die Funktion eine mehrdimensionale Arrayvariable akzeptiert (anstatt ein Array von Zeigern zu speichern, die verwaltet und gelöscht werden müssen):

template <size_t size_x, size_t size_y>
void func(double (&arr)[size_x][size_y])
{
    printf("%p\n", &arr);
}

int main()
{
    double a1[10][10];
    double a2[5][5];

    printf("%p\n%p\n\n", &a1, &a2);
    func(a1);
    func(a2);

    return 0;
}

Die print-Anweisungen sollen zeigen, dass die Arrays als Referenz übergeben werden (indem die Adressen der Variablen angezeigt werden).

Zrax
quelle
2
Sie sollten %peinen Zeiger drucken, und selbst dann müssen Sie ihn umwandeln void *, sonst wird printf()undefiniertes Verhalten aufgerufen. Darüber hinaus sollten Sie &beim Aufrufen der Funktionen nicht den Operator addressof ( ) verwenden, da die Funktionen ein Argument vom Typ erwarten double (*)[size_y], während Sie sie derzeit double (*)[10][10]und übergeben double (*)[5][5].
Wenn Sie Vorlagen verwenden, ist es besser und besser, beide Dimensionen als Vorlagenargumente festzulegen, da der Zugriff auf Zeiger auf niedriger Ebene möglicherweise vollständig vermieden wird.
Legends2k
3
Dies funktioniert nur, wenn die Größe des Arrays zur Kompilierungszeit bekannt ist.
jeb_is_a_mess
@ George Code oben in der Antwort ist genau das, was ich vorgeschlagen hatte. Es funktioniert in GCC 6.3 - Online-Demo . Haben Sie vergessen, den Parameter als Referenz zu verwenden?
Legends2k
21

Überrascht, dass dies noch niemand erwähnt hat, aber Sie können einfach eine 2D-Vorlage für [] [] -Semantik erstellen.

template <typename TwoD>
void myFunction(TwoD& myArray){
     myArray[x][y] = 5;
     etc...
}

// call with
double anArray[10][10];
myFunction(anArray);

Es funktioniert mit jeder "Array-ähnlichen" 2D-Datenstruktur, z. B. std::vector<std::vector<T>>oder einem benutzerdefinierten Typ, um die Wiederverwendung von Code zu maximieren.

LemonPi
quelle
1
Dies sollte die richtige Antwort sein. Es löst alle genannten und einige hier nicht erwähnte Probleme. Typensicherheit, Inkompatibilität der Kompilierungszeit von Arrays, keine Zeigerarithmetik, kein Typumwandeln, kein Kopieren von Daten. Funktioniert für C und C ++.
OpalApps
Nun, das funktioniert für C ++; C unterstützt keine Vorlagen. Um dies in C zu tun, wären Makros erforderlich.
Gunnar
Dies sollte die akzeptierte Antwort sein. Vielen Dank!
Sunit Gautam
20

Sie können eine Funktionsvorlage wie folgt erstellen:

template<int R, int C>
void myFunction(double (&myArray)[R][C])
{
    myArray[x][y] = 5;
    etc...
}

Dann haben Sie beide Dimensionsgrößen über R und C. Für jede Arraygröße wird eine andere Funktion erstellt. Wenn Ihre Funktion also groß ist und Sie sie mit einer Vielzahl unterschiedlicher Arraygrößen aufrufen, kann dies kostspielig sein. Sie können es jedoch als Wrapper für eine Funktion wie diese verwenden:

void myFunction(double * arr, int R, int C)
{
    arr[x * C + y] = 5;
    etc...
}

Es behandelt das Array als eindimensional und verwendet Arithmetik, um die Offsets der Indizes zu ermitteln. In diesem Fall würden Sie die Vorlage folgendermaßen definieren:

template<int C, int R>
void myFunction(double (&myArray)[R][C])
{
    myFunction(*myArray, R, C);
}
Benjamin Lindley
quelle
2
size_tist der bessere Typ für Array-Indizes als int.
Andrew Tomazos
13

anArray[10][10]ist kein Zeiger auf einen Zeiger, sondern ein zusammenhängender Speicherblock, der zum Speichern von 100 Werten vom Typ double geeignet ist. Der Compiler kann diese adressieren, da Sie die Dimensionen angegeben haben. Sie müssen es an eine Funktion als Array übergeben. Sie können die Größe der anfänglichen Dimension wie folgt weglassen:

void f(double p[][10]) {
}

Auf diese Weise können Sie jedoch keine Arrays mit der letzten Dimension außer zehn übergeben.

Die beste Lösung in C ++ ist die Verwendung std::vector<std::vector<double> >: Sie ist fast genauso effizient und wesentlich bequemer.

dasblinkenlight
quelle
1
Ich bevorzuge diese Lösung, da die Standardbibliothek sehr effizient ist - übrigens mag ich dasblinkenlight; Ich habe dasblikenlicht
mozillanerd
Fast so effizient? Ja, genau. Zeigerjagd ist immer teurer als Nicht-Zeigerjagd.
Thomas Eding
8

Ein eindimensionales Array zerfällt in einen Zeiger, der auf das erste Element im Array zeigt. Während ein 2D-Array zu einem Zeiger zerfällt, der auf die erste Zeile zeigt. Der Funktionsprototyp sollte also sein -

void myFunction(double (*myArray) [10]);

Ich würde std::vectorrohen Arrays vorziehen .

Mahesh
quelle
8

Sie können so etwas tun ...

#include<iostream>

using namespace std;

//for changing values in 2D array
void myFunc(double *a,int rows,int cols){
    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++){
            *(a+ i*rows + j)+=10.0;
        }
    }
}

//for printing 2D array,similar to myFunc
void printArray(double *a,int rows,int cols){
    cout<<"Printing your array...\n";
    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++){
            cout<<*(a+ i*rows + j)<<"  ";
        }
    cout<<"\n";
    }
}

int main(){
    //declare and initialize your array
    double a[2][2]={{1.5 , 2.5},{3.5 , 4.5}};

    //the 1st argument is the address of the first row i.e
    //the first 1D array
    //the 2nd argument is the no of rows of your array
    //the 3rd argument is the no of columns of your array
    myFunc(a[0],2,2);

    //same way as myFunc
    printArray(a[0],2,2);

    return 0;
}

Ihre Ausgabe wird wie folgt sein ...

11.5  12.5
13.5  14.5
Sagar Shah
quelle
1
Der einzige Grund, warum ich das Array in diesem Fall beschädigen würde, ist, dass man nicht weiß, wie Array-Zeiger funktionieren.
Lundin
3
Die Variable i muss mit Spalten multipliziert werden, nicht mit Zeilen, es sei denn, Spalten und Zeilen sind wie in diesem Fall gleich
Andrey Chernukha
4

Hier ist ein Beispiel für eine Vektormatrix

#include <iostream>
#include <vector>
using namespace std;

typedef vector< vector<int> > Matrix;

void print(Matrix& m)
{
   int M=m.size();
   int N=m[0].size();
   for(int i=0; i<M; i++) {
      for(int j=0; j<N; j++)
         cout << m[i][j] << " ";
      cout << endl;
   }
   cout << endl;
}


int main()
{
    Matrix m = { {1,2,3,4},
                 {5,6,7,8},
                 {9,1,2,3} };
    print(m);

    //To initialize a 3 x 4 matrix with 0:
    Matrix n( 3,vector<int>(4,0));
    print(n);
    return 0;
}

Ausgabe:

1 2 3 4
5 6 7 8
9 1 2 3

0 0 0 0
0 0 0 0
0 0 0 0
edW
quelle
2

Wir können ein 2D-Array auf verschiedene Arten an eine Funktion übergeben:

  • Mit einem einzelnen Zeiger müssen wir das 2D-Array typisieren.

    #include<bits/stdc++.h>
    using namespace std;
    
    
    void func(int *arr, int m, int n)
    {
        for (int i=0; i<m; i++)
        {
           for (int j=0; j<n; j++)
           {
              cout<<*((arr+i*n) + j)<<" ";
           }
           cout<<endl;
        }
    }
    
    int main()
    {
        int m = 3, n = 3;
        int arr[m][n] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        func((int *)arr, m, n);
        return 0;
    }
  • Verwenden des Doppelzeigers Auf diese Weise wird auch das 2d-Array typisiert

    #include<bits/stdc++.h>
    using namespace std;

   void func(int **arr, int row, int col)
   {
      for (int i=0; i<row; i++)
      {
         for(int j=0 ; j<col; j++)
         {
           cout<<arr[i][j]<<" ";
         }
         printf("\n");
      }
   }

  int main()
  {
     int row, colum;
     cin>>row>>colum;
     int** arr = new int*[row];

     for(int i=0; i<row; i++)
     {
        arr[i] = new int[colum];
     }

     for(int i=0; i<row; i++)
     {
         for(int j=0; j<colum; j++)
         {
            cin>>arr[i][j];
         }
     }
     func(arr, row, colum);

     return 0;
   }
Hautausschläge
quelle
1

Eine wichtige Sache für die Übergabe mehrdimensionaler Arrays ist:

  • First array dimension muss nicht angegeben werden.
  • Second(any any further)dimension muss angegeben werden.

1.Wenn nur die zweite Dimension global verfügbar ist (entweder als Makro oder als globale Konstante)

`const int N = 3;

`void print(int arr[][N], int m)
{
int i, j;
for (i = 0; i < m; i++)
  for (j = 0; j < N; j++)
    printf("%d ", arr[i][j]);
}`

int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print(arr, 3);
return 0;
}`

2.Verwenden eines einzelnen Zeigers : Bei dieser Methode müssen wir das 2D-Array bei der Übergabe an die Funktion typisieren .

`void print(int *arr, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
  for (j = 0; j < n; j++)
    printf("%d ", *((arr+i*n) + j));
 }

`int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3, n = 3;

// We can also use "print(&arr[0][0], m, n);"
print((int *)arr, m, n);
return 0;
}`
klangvoll
quelle
0

Sie können dazu die Vorlagenfunktion in C ++ verwenden. Ich habe so etwas gemacht:

template<typename T, size_t col>
T process(T a[][col], size_t row) {
...
}

Das Problem bei diesem Ansatz besteht darin, dass für jeden von Ihnen angegebenen Wert von col die neue Funktionsdefinition mithilfe der Vorlage instanziiert wird. damit,

int some_mat[3][3], another_mat[4,5];
process(some_mat, 3);
process(another_mat, 4);

Instanziiert die Vorlage zweimal, um zwei Funktionsdefinitionen zu erstellen (eine mit col = 3 und eine mit col = 5).

vantony
quelle
0

Wenn Sie weitergeben wollen int a[2][3]zu void func(int** pp)müssen Sie Hilfsschritte wie folgt.

int a[2][3];
int* p[2] = {a[0],a[1]};
int** pp = p;

func(pp);

Da die erste [2]implizit angegeben werden kann, kann sie weiter vereinfacht werden als.

int a[][3];
int* p[] = {a[0],a[1]};
int** pp = p;

func(pp);
Geldorientierter Programmierer
quelle
0

Wenn Sie ein dynamisches 2D-Array an eine Funktion übergeben möchten, kann die Verwendung einiger Zeiger für Sie hilfreich sein.

void func1(int *arr, int n, int m){
    ...
    int i_j_the_element = arr[i * m + j];  // use the idiom of i * m + j for arr[i][j] 
    ...
}

void func2(){
    ...
    int arr[n][m];
    ...
    func1(&(arr[0][0]), n, m);
}
Purusharth Verma
quelle
0

Sie dürfen die Dimension ganz links weglassen und haben zwei Möglichkeiten:

void f1(double a[][2][3]) { ... }

void f2(double (*a)[2][3]) { ... }

double a[1][2][3];

f1(a); // ok
f2(a); // ok 

Dies gilt auch für Zeiger:

// compilation error: cannot convert ‘double (*)[2][3]’ to ‘double***’ 
// double ***p1 = a;

// compilation error: cannot convert ‘double (*)[2][3]’ to ‘double (**)[3]’
// double (**p2)[3] = a;

double (*p3)[2][3] = a; // ok

// compilation error: array of pointers != pointer to array
// double *p4[2][3] = a;

double (*p5)[3] = a[0]; // ok

double *p6 = a[0][1]; // ok

Der Zerfall eines N-dimensionalen Arrays in einen Zeiger auf ein N-1-dimensionales Array ist nach dem C ++ - Standard zulässig , da Sie die am weitesten links stehende Dimension verlieren und dennoch korrekt auf Array-Elemente mit N-1-Dimensionsinformationen zugreifen können.

Details hier

Obwohl, Arrays und Zeiger sind nicht die gleichen : eine Anordnung in einen Zeiger des Zerfalls kann, sondern ein Zeiger nicht trägt Zustand über die Größe / Konfiguration der Daten , auf die sie verweist.

A char **ist ein Zeiger auf einen Speicherblock, der Zeichenzeiger enthält , die selbst auf Speicherblöcke von Zeichen zeigen. A char [][]ist ein einzelner Speicherblock, der Zeichen enthält. Dies hat Auswirkungen darauf, wie der Compiler den Code übersetzt und wie die endgültige Leistung sein wird.

Quelle

luca
quelle