Zusammenfassung zwischen eindimensionalen/zweidimensionalen C/C++-Arrays und Zeigern

Zunächst stelle ich die folgende Frage, Leser: Wenn Sie wissen, was es bedeutet, wird Ihnen dieser Artikel nicht weiterhelfen. Der Autor ist auch ein Neuling, aber vor kurzem habe ich die Grundlagen von C überprüft und war plötzlich verwirrt Ich habe das Problem herausgefunden, also schreibe ich diesen Blog hier, ohne um Hilfe zu bitten, sondern nur darum, dass ich ihn in Zukunft schnell überprüfen kann.

Beobachten Sie das Problem im folgenden Code sorgfältig und beachten Sie die Ausgabeinformationen

#include <QDebug>

///一维数组
///问题1:为什么a1不能自增(报语法错误,根本编译不过去),而p1却可以自增呢?
///问题2:为什么a1和&a1的输出值是一样的呢?
void linearArray()
{
    int a[3] = {1277,2,3};
    int *p = a;
    p++;
    //a1++;
    qDebug() << a << &a << *p << *a;

/*
    0x66f918 0x66f918 2 1277
*/
}


///二维数组
///问题1:为什么 sizeof(a)的输出结果是48?
///问题2:为什么下面的第二条输出语句输出的内容全部一样?并且他们都有什么含义
///问题3:为什么第四条输出语句会是666 和 4?
///问题4:int * p3 = a;为什么会报错,为什么必须加强制类型转换后才能编译过去:int * p3 = (int*)a,以及为什么p3+=2后的输出是777?
void twoDimensionalArray()
{
    int a[3][4];
    a[0][0] = 555;
    a[0][1] = 666;
    a[0][2] = 777;
    a[1][0] = 888;
    qDebug() << sizeof(a);

    qDebug() << a << &a << a[0] << &a[0] << *a;

    qDebug() << sizeof (a[0]) << sizeof (*a);

    int * p2 = a[0];
    p2++;
    qDebug() << *p2 << sizeof(a[0])/sizeof(int);

    //int * p3 = a;语法错误?
    int * p3 = (int*)a;
    p3 += 2;//相当于两次自增
    qDebug() << *p3;

/*
输出信息:
    48
    0x12ffb9c 0x12ffb9c 0x12ffb9c 0x12ffb9c 0x12ffb9c
    16 16
    666 4
    777
*/
}

int main(int argc, char *argv[])
{
    linearArray();
    //twoDimensionalArray();
}

Lassen Sie uns zunächst über eindimensionale Arrays sprechen:

        Schüler, die sich möglicherweise mit der C-Sprache auskennen, wissen, dass der Array-Name in der C-Sprache die erste Adresse des Arrays ist . Viele Leute wissen, dass der Array-Name nicht selbst inkrementiert werden kann , aber er kann selbst inkrementiert werden, nachdem er einem Zeiger zugewiesen wurde vom gleichen Typ wie sein Element (z. B. die oben auskommentierten a1++-Anweisungen und p1++-Anweisungen).

Das liegt daran, dass sich der Array-Name in der aktuellen Funktion (der Funktion, die das Array definiert) befindet . Obwohl sein Wert die erste Adresse des Arrays ist, ist sein (Array-Name)-Typ kein Zeiger , sondern ein Array! Genauer gesagt kann man es sogar als Konstante verstehen! Dies erklärt auch, warum die Ausführung von {sizeof(array name)➗sizeof(array element type)} in der aktuellen Funktion die Anzahl der Array-Elemente ermitteln kann, da es sich überhaupt nicht um einen Zeiger, sondern um eine Konstante, sondern um den Wert davon handelt konstant Der Wert ist seine erste Adresse, und die Schrittgröße dieser Konstante (tatsächlich ist die Schrittgröße nicht genau, die Schrittgröße ist immer noch aus der Perspektive des Zeigers, aber leicht zu verstehen) ist ihre vollständige Größe . Wenn Sie Selbstinkrementierungsoperationen für Konstanten ausführen, ist das unlogisch, i++ ist in Ordnung, 3++ jedoch nicht, das ist der Grund.

( ps: Nachdem der Array-Name als Parameter übergeben wurde, degeneriert er in die Adresse des ersten Elements des Arrays . Aber sizeof ist keine Funktion, sondern ein Operator, also machen Sie sich keine Sorgen, dass er in einen Zeiger degeneriert.)

Der Grund, warum der Name des Arrays a1 nach der Zuweisung zum Zeiger p1 selbst inkrementiert werden kann, liegt darin, dass ihm tatsächlich die erste Adresse des ersten Elements im Array zugewiesen wird , die erste Adresse des ersten Elements jedoch genau mit der ersten Adresse des ersten Elements übereinstimmt erste Adresse des Arrays. Die Größe des Elementtyps, auf den p1 zeigt, ist die Schrittgröße von p1, sodass nach p1++ das erste Element auf das zweite Element zeigt.

int * p1 = a1; Es wird oft gesagt, dass die erste Adresse des Arrays dem Zeiger p1 zugewiesen ist, was überhaupt nicht korrekt ist. Es sollte gesagt werden: „Weisen Sie dem Zeiger die Adresse des ersten Elements dieses Zeigers zu.“ p“ ist genauer . Zunächst wissen wir, dass der Wert der Konstante a1 eine Adresse ist, er weist diese Adresse einfach einem Zeiger vom Typ int zu und die Schrittgröße von int ist die Schrittgröße eines einzelnen Elements des Arrays, also sollte es so sein Man kann sagen, dass das erste Element dieses Zeigers ist p zugewiesen

&a ist ein Array-Zeiger. Wenn a als Ganzes und nicht als Zeiger verstanden wird, ist &a ein Array-Zeiger. Da die Adresse von a auch die erste Adresse des Arrays ist, ist die Ausgabe dieselbe, aber die Schrittgröße ist die Schrittgröße des gesamten Arrays.

Warum gibt *a das erste Element des Arrays aus? Da oben gesagt wurde, dass der Array-Name in dieser Funktion kein Zeiger, sondern ein ganzes Array ist, warum erhält *Array-Name dann den Wert des ersten Elements? Hier ist eine kurze Erläuterung der Rolle von „*“ im Array. Es wird vor dem Array-Namen als Wertoperator verwendet, um den Wert des ersten Elements des Arrays abzurufen . Das heißt, *a == a[0], der Grund für das Verwerfen dieses Konzepts ist, dass ich befürchte, dass das zweidimensionale Array später schwindelig wird (ich habe die C-Sprache schon lange nicht mehr verwendet und Ich habe die Rolle von * im Array vergessen, hiermit schreibe es auf).

Nachdem wir die Eigenschaften des oben genannten eindimensionalen Arrays gemeistert haben, schauen wir uns das zweidimensionale Array an:

Frage eins:

         Beziehen Sie sich wie bei einem eindimensionalen Array auf das obige eindimensionale Array

Frage zwei:

        a: a ist der Name des Arrays und der Wert des Array-Namens ist die erste Adresse des Arrays, daher wird die erste Adresse des Arrays ausgegeben. Aber der Typ von a ist ein Array, kein Zeiger.

        &a: ist ein Array-Zeiger und die Schrittgröße ist die Schrittgröße des gesamten zweidimensionalen Arrays. Sie können auf das eindimensionale Array oben verweisen

a[0]: ist der Array-Name des         ersten Elements von a (auch ein Array) . Dies erklärt auch, warum die Ausgabe von qDebug() << sizeof (a[0]); 16 ist.

        &a[0]: Wie oben erwähnt, können Sie a[0] als Array-Namen verwenden, dann bedeutet &a[0] die Adresse des ersten Elements des Arrays a[0], was genau die Lösung für die ungeklärte Frage drei ist

        *a: Wie oben erwähnt, können Sie die Erklärung von * im eindimensionalen Array oben sehen. *a ist der Array-Zeiger, der das erste eindimensionale Array darstellt, das heißt, Sie können a hier als eins betrachten. dimensionales Array, und *a ist der Array-Name dieses eindimensionalen Arrays.

        Nach der Konvertierung in ein eindimensionales Array ist *a == a[0] leicht zu verstehen, was die dritte Ausgabeinformation erklärt

Frage vier:

        Da die Typen nicht übereinstimmen, muss die Zuweisung falsch sein, einer ist ein ganzzahliger Zeiger und der andere ein Array-Typ.

        Nachdem die obligatorische Typkonvertierung für den Array-Namen durchgeführt wurde, stellt der Array-Name die erste Adresse des Arrays dar. Dies entspricht der Zuweisung der Adresse des ersten Elements des Arrays zum Zeiger p3 und der Schrittgröße dieses Zeigers Der Formungsschritt. Lang, also nach dem Hinzufügen von zwei Schritten beträgt die Ausgabe 777

        

Ich denke du magst

Origin blog.csdn.net/qq_25704799/article/details/127399223
Empfohlen
Rangfolge