Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> C Sprache

Pointer und mehrdimensionale Arrays in C meistern

In der C-Sprache ist ein Array eine Sammlung von Werten gleichen Typs, die in zusammenhängenden Speicherbereichen gespeichert sind. Jedes Element in einem Array (eindimensional oder mehrdimensional) wird durch einen oder mehrere eindeutige ganzzahlige Indizes identifiziert.

Ein Pointer hingegen speichert die Adresse einer Variable. Die Adresse des 0. Elements in einem Array ist der Pointer des Arrays. Man kann den „Dereferenzierungsoperator“ nutzen, um auf den Wert zuzugreifen, auf den ein Pointer verweist.

Man kann eindimensionale, zweidimensionale oder mehrdimensionale Arrays in C deklarieren. Der Begriff „Dimension“ bezieht sich auf die Anzahl der Indizes, die zur Identifikation eines Elements in einer Sammlung erforderlich sind.

Pointer und eindimensionale Arrays

In einem eindimensionalen Array wird jedes Element durch einen einzelnen Integer identifiziert:

int a[5] = {1, 2, 3, 4, 5};

Hier ist die Zahl „1“ am Index 0, „2“ am Index 1, usw.

Eine Variable, die die Adresse des 0. Elements speichert, ist sein Pointer:

int *x = &a[0];

Einfach ausgedrückt: Der Name des Arrays zeigt auch auf die Adresse des 0. Elements. Man kann also auch diesen Ausdruck nutzen:

int *x = a;

Beispiel

Da der Wert des Pointers um die Größe des Datentyps inkrementiert, bewegt x++ den Pointer zum nächsten Element im Array.

#include <stdio.h>
int main(){
    int arr[] = {1, 2, 3, 4, 5};
    int length = sizeof(arr) / sizeof(arr[0]);
    int i = 0;
    int *ptr = arr;
    while (i < length){
        printf("arr[%d]: %d \n", i, *(ptr + i));
        i++;
    }
    return 0;
}

Ausgabe

arr[0]: 1
arr[1]: 2
arr[2]: 3
arr[3]: 4
arr[4]: 5

Pointer und zweidimensionale Arrays

Wenn ein eindimensionales Array wie eine Liste von Elementen ist, ist ein zweidimensionales Array wie eine Tabelle oder Matrix.

Die Elemente in einem 2D-Array können logisch in Zeilen und Spalten angeordnet betrachtet werden. Daher wird die Position jedes Elements durch zwei Indizes bestimmt: Zeilennummer und Spaltennummer. Beide Indizes beginnen bei „0“.

int arr[2][2];

Ein solches Array wird logisch so dargestellt:

Col0 Col1 Col2
Row0 arr[0][0] arr[0][1] arr[0][2]
Row1 arr[1][0] arr[1][1] arr[1][2]
Row2 arr[2][0] arr[2][1] arr[2][2]

Zu beachten: Die tabellarische Anordnung ist nur eine logische Repräsentation. Der Compiler alloziert einen Block zusammenhängender Bytes. In C erfolgt die Array-Allokation zeilenweise (row-major), d. h. die Elemente werden zeilenweise in das Array eingelesen.

Hier deklarieren wir ein 2D-Array mit drei Zeilen und vier Spalten (die Zahl in der ersten eckigen Klammer bezieht sich immer auf die Zeilenanzahl):

int arr[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

Der Compiler alloziert den Speicher für das obige 2D-Array zeilenweise. Angenommen, das erste Element liegt bei Adresse 1000 und die Größe von int beträgt 4 Bytes, erhalten die Elemente folgende Speicheradressen:

Row 0 Row 1 Row 2
Value 1 2 3 4 5 6 7 8 9 10 11 12
Address 1000 1004 1008 1012 1016 1020 1024 1028 1032 1036 1040 1044

Wir weisen die Adresse des ersten Elements des Arrays num dem Pointer ptr mittels Adressoperator & zu:

int *ptr = &arr[0][0];

Beispiel 1

Wenn der Pointer um 1 inkrementiert wird, bewegt er sich zur nächsten Adresse. Alle 12 Elemente im „3x4“-Array können in einer Schleife wie folgt zugegriffen werden:

#include <stdio.h>
int main(){
    int arr[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12},
    };
    // Pointer ptr zeigt auf Array num
    int *ptr = &arr[0][0];
    int i, j, k = 0;
    // Elemente des Arrays num via Pointer ptr ausgeben
    for (i = 0; i < 3; i++){
        for (j = 0; j < 4; j++){
            printf("%d ", *(ptr + k));
            k++;
        }
        printf("\n");
    }
    return 0;
}

Ausgabe

1 2 3 4
5 6 7 8
9 10 11 12

Im Allgemeinen kann die Adresse jedes Elements des Arrays mit folgender Formel berechnet werden:

Adresse von Element an i-ter Zeile und j-ter Spalte = baseAddress + [(i * anzahl_spalten + j) * sizeof(array_type)]

In unserem 3x4-Array:

Adresse von arr[2][2] = 1000 + (2*4 + 2)*4 = 1044

Man kann sich auf die obige Tabelle beziehen – sie bestätigt, dass die Adresse von „arr[2][2]“ 1044 ist (Anm.: im Originaltext stand arr[3][4], korrigiert auf 0-basiert).

Beispiel 2

Nutzen wir den Dereferenzierungs-Pointer, um den Wert an der Adresse zu holen. Wir verwenden die Formel, um das Array mit seinem Pointer zu traversieren:

#include <stdio.h>
int main(){
    // 2d array
    int arr[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    int ROWS = 3, COLS = 4;
    int i, j;
    // pointer
    int *ptr = &arr[0][0];
    // Element des Arrays via Pointer ptr ausgeben
    for (i = 0; i < ROWS; i++){
        for (j = 0; j < COLS; j++) {
            printf("%4d ", *(ptr + (i * COLS + j)));
        }
        printf("\n");
    }
    return 0;
}

Ausgabe

   1    2    3    4
   5    6    7    8
   9   10   11   12

Pointer und dreidimensionale Arrays

Ein dreidimensionales Array ist ein Array von zweidimensionalen Arrays. Ein solches Array wird mit drei Subscripts deklariert:

int arr[x][y][z];

Dieses Array kann als „x“ Anzahl an Layern von Tabellen betrachtet werden, wobei jede Tabelle „y“ Zeilen und „z“ Spalten hat.

Ein Beispiel für ein 3D-Array:

int arr[3][3][3] = {
    { {11, 12, 13}, {14, 15, 16}, {17, 18, 19} },
    { {21, 22, 23}, {24, 25, 26}, {27, 28, 29} },
    { {31, 32, 33}, {34, 35, 36}, {37, 38, 39} },
};

Ein Pointer auf das 3D-Array kann deklariert werden als:

int *ptr = &arr[0][0][0];

Da der Name des Arrays selbst die Adresse des 0. Elements ist, können wir den Pointer eines 3D-Arrays auch so schreiben:

int *ptr = arr;

Jeder Layer aus „x“ Zeilen und „y“ Spalten belegt:

x * y * sizeof(data_type) Bytes.

Angenommen, der dem 3D-Array „arr“ allozierte Speicher beginnt bei Adresse 1000, startet der zweite Layer (mit i = 1) bei 1000 + (3 * 3) * 4 = 1036 Byte-Position.

ptr = Basisadresse des 3D-Arrays arr

Wenn JMAX die Zeilenanzahl und KMAX die Spaltenanzahl ist, dann ist die Adresse des Elements an der 0. Zeile und 0. Spalte des 1. Slices:

arr[1][0][0] = ptr + (1 * JMAX * KMAX)

Die Formel für den Wert eines Elements an der j-ten Zeile und k-ten Spalte des i-ten Slices lautet:

arr[i][j][k] = *(ptr + (i * JMAX * KMAX) + (j * KMAX + k))

Beispiel: 3D-Array mittels Pointer-Dereferenzierung ausgeben

Nutzen wir diese Formel, um das 3D-Array mit Pointer-Dereferenzierung auszugeben:

#include <stdio.h>
int main(){
    int i, j, k;
    int arr[3][3][3] = {
        { {11, 12, 13}, {14, 15, 16}, {17, 18, 19} },
        { {21, 22, 23}, {24, 25, 26}, {27, 28, 29} },
        { {31, 32, 33}, {34, 35, 36}, {37, 38, 39} },
    };
    int JMAX = 3, KMAX = 3;
    int *ptr = arr; // &arr[0][0][0];
    for(i = 0; i < 3; i++){
        for(j = 0; j < 3; j++){
            for(k = 0; k < 3; k++){
                printf("%d ", *(ptr + (i * JMAX * KMAX) + (j * KMAX + k)));
            }
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

Ausgabe

11 12 13
14 15 16
17 18 19

21 22 23
24 25 26
27 28 29

31 32 33
34 35 36
37 38 39

Im Allgemeinen ist der Zugriff auf ein Array mit einem Pointer dem Zugriff mit Subscript-Darstellung recht ähnlich. Der Hauptunterschied: Die subscriptierte Deklaration alloziert Speicher statisch, während Pointer für dynamische Speicherallokation genutzt werden können.

Um ein mehrdimensionales Array an eine Funktion zu übergeben, muss man Pointer statt Subscripts verwenden. Allerdings ist die Nutzung eines subscriptierten Arrays bequemer als Pointer, die für neue Lernende schwierig sein können.

C Sprache

  1. C-Programmierung meistern: Umfassendes PDF-Tutorial für Einsteiger
  2. Guru99: Umfassende Online-Tutorials & Business-Software-Reviews
  3. C++ Call by Reference: Mit Zeigern – Praktische Beispiele
  4. C# Reflection: Laufzeit-Typinformation & dynamische Programmierung
  5. Unsicherer C#-Code meistern: Zeiger und Speicherverwaltung
  6. Datei-I/O in C meistern: Erstellen, Öffnen & Verwalten von Dateien
  7. Top 15 C++ Online-Kurse, um die Sprache zu meistern (2024 Update)
  8. C#-Interfaces meistern: Definition, Implementierung und praktische Anwendungsfälle
  9. Zeiger auf Zeichen und Funktionsverwendung in C meistern
  10. C# Collections meistern: Praktisches Tutorial mit Real-World-Beispielen