wake-up-neo.net

Zeigerausdrücke: * ptr ++, * ++ ptr und ++ * ptr

Vor kurzem bin ich auf dieses Problem gestoßen, das ich selbst nicht verstehen kann.

Was bedeuten diese drei Ausdrücke WIRKLICH?

*ptr++
*++ptr
++*ptr

Ich habe es mit Ritchie versucht. Aber leider konnte er nicht folgen, was er über diese 3 Operationen erzählte.

Ich weiß, dass sie alle ausgeführt werden, um den Zeiger/den Wert, auf den gezeigt wird, zu erhöhen. Ich kann auch vermuten, dass es viele Dinge über Rangfolge und Reihenfolge der Bewertung gibt. So wie man zuerst den Zeiger inkrementiert und dann den Inhalt dieses Zeigers abruft, ruft man einfach den Inhalt ab und erhöht dann den Zeiger usw. usw. Wie Sie sehen, habe ich kein klares Verständnis für ihre tatsächlichen Operationen , die ich so schnell wie möglich klären möchte. Aber ich bin wirklich verloren, als ich die Chance bekomme, sie in Programmen anzuwenden. Zum Beispiel:

int main()
{
    const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
    return 0;
}

gibt mir diese Ausgabe:

Ello

Aber meine Erwartung war, dass es Hello ausgeben würde. Eine letzte Anfrage - Bitte geben Sie mir Beispiele dafür, wie jeder Ausdruck in einem bestimmten Codeausschnitt funktioniert. Da die meiste Zeit nur ein Absatz der Theorie über meinen Kopf geflogen wird.

110
allocated

Hier ist eine detaillierte Erklärung, von der ich hoffe, dass sie hilfreich ist. Beginnen wir mit Ihrem Programm, da es am einfachsten zu erklären ist.

int main()
{
    const char *p = "Hello";
    while(*p++)
        printf("%c",*p);
    return 0;
}

Die erste Aussage:

const char* p = "Hello";

deklariert p als Zeiger auf char. Wenn wir "Zeiger auf ein char" sagen, was bedeutet das? Dies bedeutet, dass der Wert von p die Adresse eines char ist; p teilt uns mit, wo im Speicher Platz für ein char ist.

Die Anweisung initialisiert auch p, um auf das erste Zeichen im Zeichenfolgenliteral "Hello" zu verweisen. Für diese Übung ist es wichtig zu verstehen, dass p nicht auf die gesamte Zeichenfolge, sondern nur auf das erste Zeichen 'H' verweist. Immerhin ist p ein Zeiger auf ein char, nicht auf die gesamte Zeichenfolge. Der Wert von p ist die Adresse des 'H' in "Hello".

Dann richten Sie eine Schleife ein:

while (*p++)

Was bedeutet die Schleifenbedingung *p++? Hier wirken drei Dinge, die dieses Rätsel machen (zumindest bis Vertrautheit einsetzt):

  1. Die Rangfolge der beiden Operatoren postfix ++ und indirection *
  2. Der Wert eines Postfix-Inkrementausdrucks
  3. Der Nebeneffekt eines Postfix-Inkrementausdrucks

1. Vorrang. Ein kurzer Blick auf die Rangfolgetabelle für Operatoren zeigt, dass das Postfix-Inkrement einen höheren Rang hat (16) als die Dereferenzierung/Indirektion (15). Dies bedeutet, dass der komplexe Ausdruck *p++ wie folgt gruppiert wird: *(p++). Das heißt, der Teil * wird auf den Wert des Teils p++ angewendet. Nehmen wir also zuerst den Teil p++.

2. Postfix-Ausdruckswert. Der Wert von p++ ist der Wert von pvor dem Inkrement. Wenn Sie haben:

int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);

die Ausgabe wird sein:

7
8

weil i++ vor dem Inkrement zu i ausgewertet wird. In ähnlicher Weise wird p++ auf den aktuellen Wert von p ausgewertet. Wie wir wissen, ist der aktuelle Wert von p die Adresse von 'H'.

So, jetzt wurde der p++ Teil von *p++ ausgewertet; Dies ist der aktuelle Wert von p. Dann passiert der Teil *. *(current value of p) bedeutet: Zugriff auf den Wert unter der Adresse von p. Wir wissen, dass der Wert an dieser Adresse 'H' ist. Der Ausdruck *p++ ergibt also 'H'.

Jetzt warte eine Minute, sagst du. Wenn *p++ zu 'H' ausgewertet wird, warum wird dieser 'H' nicht im obigen Code gedruckt? Das ist, wo Nebenwirkungen hereinkommen.

. Nebenwirkungen des Postfix-Ausdrucks. Das Postfix ++ hat den Wert ​​des aktuellen Operanden, aber den Nebeneffekt ​​des Inkrementierens dieses Operanden. Huh? Schauen Sie sich diesen int Code noch einmal an:

int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);

Wie bereits erwähnt, lautet die Ausgabe:

7
8

Wenn i++ in der ersten printf() ausgewertet wird, wird es mit 7 bewertet. Der C-Standard garantiert jedoch, dass zu einem Zeitpunkt vor dem Beginn der Ausführung der zweiten printf() die Nebenwirkung des ++ Operator wird stattgefunden haben. Das heißt, bevor die zweite printf() auftritt, wurde i als Ergebnis des Operators ++ in der ersten printf() inkrementiert. Dies ist im Übrigen eine der wenigen Garantien, die der Standard für das Timing von Nebenwirkungen gibt.

Wenn in Ihrem Code der Ausdruck *p++ ausgewertet wird, wird er zu 'H' ausgewertet. Aber wenn Sie dazu kommen:

printf ("%c", *p)

diese nervige Nebenwirkung ist aufgetreten. p wurde erhöht. Whoa! Es zeigt nicht mehr auf 'H', sondern auf ein Zeichen nach 'H': also auf das 'e'. Das erklärt Ihre cockneyfied Ausgabe:

Ello

Daher der Chor hilfreicher (und genauer) Vorschläge in den anderen Antworten: Um die empfangene Aussprache "Hello" und nicht das Cockney-Gegenstück auszudrucken, benötigen Sie so etwas wie

while (*p)
    printf ("%c", *p++);

So viel dazu. Was ist mit dem Rest? Sie fragen nach den Bedeutungen dieser:

*ptr++
*++ptr
++*ptr

Wir haben gerade über den ersten gesprochen, also schauen wir uns den zweiten an: *++ptr.

In unserer früheren Erklärung haben wir gesehen, dass das Postfix-Inkrement p++ einen bestimmten Vorrang, einen Wert ​​und einen Nebeneffekt ​​hat. Das Präfixinkrement ++p hat den gleichen Nebeneffekt ​​wie sein Postfix-Gegenstück: Es erhöht seinen Operanden um 1. Es hat jedoch ein anderes Vorrang und ein anderes - Wert.

Das Präfixinkrement hat eine niedrigere Priorität als das Postfix. es hat Vorrang 15. Mit anderen Worten, es hat den gleichen Vorrang wie der Dereferenzierungs-/Indirektionsoperator *. In einem Ausdruck wie

*++ptr

was zählt, ist nicht die Rangfolge: Die beiden Operatoren sind in der Rangfolge identisch. Also Assoziativität ​​setzt ein. Das Präfixinkrement und der Indirektionsoperator haben Rechts-Links-Assoziativität. Aufgrund dieser Assoziativität wird der Operand ptr mit dem Operator ganz rechts ++ vor dem Operator ganz links, *, gruppiert. Mit anderen Worten, der Ausdruck wird in *(++ptr) gruppiert. Wie bei *ptr++, aber aus einem anderen Grund, wird auch hier der * -Teil auf den Wert des ++ptr -Teils angewendet.

Was ist das für ein Wert? Der Wert des Präfixinkrementausdrucks ist der Wert des Operanden nach dem Inkrement. Dies macht es zu einer ganz anderen Bestie als der Postfix-Inkrement-Operator. Angenommen, Sie haben:

int i = 7;
printf ("%d\n", ++i);
printf ("%d\n", i);

Die Ausgabe wird sein:

8
8

... anders als beim Postfix-Operator. Ebenso, wenn Sie:

const char* p = "Hello";
printf ("%c ", *p);    // note space in format string
printf ("%c ", *++p);  // value of ++p is p after the increment
printf ("%c ", *p++);  // value of p++ is p before the increment
printf ("%c ", *p);    // value of p has been incremented as a side effect of p++

die Ausgabe wird sein:

H e e l                // good dog

Siehst du warum

Nun kommen wir zu dem dritten Ausdruck, nach dem Sie gefragt haben, ++*ptr. Das ist eigentlich das schwierigste. Beide Operatoren haben dieselbe Priorität und Rechts-Links-Assoziativität. Dies bedeutet, dass der Ausdruck in ++(*ptr) gruppiert wird. Der Teil ++ wird auf den Wert des Teils *ptr angewendet.

Also, wenn wir haben:

char q[] = "Hello";
char* p = q;
printf ("%c", ++*p);

das überraschend egoistische Ergebnis wird sein:

I

Was?! Okay, der Teil *p wird zu 'H' ausgewertet. Dann kommt der ++ ins Spiel, an welchem ​​Punkt er auf den 'H' angewendet wird, überhaupt nicht auf den Zeiger! Was passiert, wenn Sie 'H' um 1 erhöhen? Sie erhalten 1 plus den ASCII Wert von 'H', 72; Sie erhalten 73. Stellen Sie das als ein char dar, und Sie erhalten das char mit dem ASCII-Wert von 73: 'I'.

Das kümmert sich um die drei Ausdrücke, nach denen Sie in Ihrer Frage gefragt haben. Hier ist eine weitere, im ersten Kommentar zu Ihrer Frage erwähnte:

(*ptr)++ 

Das ist auch interessant. Wenn Sie haben:

char q[] = "Hello";
char* p = q;
printf ("%c", (*p)++);
printf ("%c\n", *p);

es wird Ihnen diese begeisterte Ausgabe geben:

HI

Was ist los? Auch hier handelt es sich um Vorrang, Ausdruckswert ​​und Nebenwirkungen. Aufgrund der Klammern wird der Teil *p als primärer Ausdruck behandelt. Primäre Ausdrücke sind wichtiger als alles andere. sie werden zuerst ausgewertet. Und *p wird, wie Sie wissen, zu 'H' ausgewertet. Der Rest des Ausdrucks, der Teil ++, wird auf diesen Wert angewendet. In diesem Fall wird (*p)++ zu 'H'++.

Was ist der Wert von 'H'++? Wenn Sie 'I' gesagt haben, haben Sie (bereits!) Unsere Diskussion von Wert vs. Nebeneffekt mit Postfix-Inkrement vergessen. Denken Sie daran, dass 'H'++ den Wert aktueller Wert von'H' ergibt. Die erste printf() gibt 'H' aus. Als Nebeneffekt ​​wird dann 'H' zu 'I' inkrementiert. Die zweite printf() gibt den 'I' aus. Und du hast deinen fröhlichen Gruß.

Okay, aber in den letzten beiden Fällen, warum brauche ich das?

char q[] = "Hello";
char* p = q;

Warum kann ich nicht einfach so etwas haben?

/*const*/ char* p = "Hello";
printf ("%c", ++*p);   // attempting to change string literal!

Weil "Hello" ein String-Literal ist. Wenn Sie ++*p versuchen, versuchen Sie, den 'H' in der Zeichenfolge in 'I' zu ändern, wodurch die gesamte Zeichenfolge "Iello" erstellt wird. In C sind Zeichenfolgenliterale schreibgeschützt. Der Versuch, sie zu ändern, ruft undefiniertes Verhalten auf. "Iello" ist auch in Englisch undefiniert, aber das ist nur Zufall.

Umgekehrt kann man nicht haben

char p[] = "Hello";
printf ("%c", *++p);  // attempting to modify value of array identifier!

Warum nicht? Denn in diesem Fall ist p ein Array. Ein Array ist kein veränderbarer l-Wert. Sie können nicht ändern, wohin p vor oder nach dem Inkrementieren oder Dekrementieren zeigt, da der Name des Arrays so funktioniert, als wäre er ein konstanter Zeiger. (Das ist nicht das, was es eigentlich ist; das ist nur eine bequeme Art, es zu betrachten.)

Zusammenfassend sind hier die drei Dinge, nach denen Sie gefragt haben:

*ptr++   // effectively dereferences the pointer, then increments the pointer
*++ptr   // effectively increments the pointer, then dereferences the pointer
++*ptr   // effectively dereferences the pointer, then increments dereferenced value

Und hier ist eine vierte, die genauso viel Spaß macht wie die anderen drei:

(*ptr)++ // effectively forces a dereference, then increments dereferenced value

Der erste und der zweite stürzen ab, wenn ptr tatsächlich eine Array-ID ist. Der dritte und vierte stürzt ab, wenn ptr auf ein String-Literal zeigt.

Hier hast du es. Ich hoffe, es ist jetzt alles Kristall. Sie waren ein tolles Publikum und ich werde die ganze Woche hier sein.

247
verbose

Angenommen, ptr zeigt auf das i-te Element des Arrays arr.

  1. *ptr++ wird zu arr[i] ausgewertet und setzt ptr so, dass sie auf das (i + 1) -te Element von arr zeigt. Es ist äquivalent zu *(ptr++).

  2. *++ptr setzt ptr so, dass er auf das (i + 1) -te Element von arr zeigt, und wertet arr[i+1] aus. Es ist äquivalent zu *(++ptr).

  3. ++*ptr erhöht arr[i] um eins und wertet seinen erhöhten Wert aus. Der Zeiger ptr bleibt unberührt. Es ist äquivalent zu ++(*ptr).

Es gibt noch eine weitere, aber Sie benötigen Klammern, um es zu schreiben:

  1. (*ptr)++ erhöht arr[i] um eins und wertet ihn aus, bevor er erhöht wird; Der Zeiger ptr bleibt wieder unberührt.

Den Rest kannst du selbst herausfinden; Es wurde auch von @ Jaguar beantwortet.

43
nickie

*ptr++ : post increment a pointer ptr

*++ptr : Pre Increment a pointer ptr

++*ptr : preincrement the value at ptr location

Lesen Sie hier über Operatoren für Pre-Increment und Post-Inkrement


Dies gibt Hello als Ausgabe aus

int main()
{
    const char *p = "Hello";
    while(*p)
         printf("%c",*p++);//Increment the pointer here 
    return 0;
}
13
Jainendra

Die Bedingung in Ihrer Schleife ist schlecht: 

while(*p++)
    printf("%c",*p);

Ist das gleiche wie 

while(*p)
{
    p++;
    printf("%c",*p);
}

Und das ist falsch, das sollte sein:

while(*p)
{
    printf("%c",*p);
    p++;
} 

*ptr++ ist das gleiche wie *(ptr++), das ist:

const char  *ptr = "example";
char  value;

value = *ptr;
++ptr;
printf("%c", value); // will print 'e'

*++ptr ist das gleiche wie *(++ptr), das ist:

const char  *ptr = "example";
char  value;

++ptr;
value = *ptr;
printf("%c", value); // will print 'x'

++*ptr ist das gleiche wie ++(*ptr), das ist:

const char  *ptr = "example";
char  value;

value = *ptr;
++value;
printf("%c", value); // will print 'f' ('e' + 1)
7
nouney

Sie haben Recht zu Vorrang, beachten Sie, dass der * Vorrang vor dem Inkrement hat, nicht aber vor dem Postfix-Inkrement. So ist diese Aufteilung:

*ptr++ - von links nach rechts dereferenzieren, den Zeiger dereferenzieren und dann den Zeigerwert inkrementieren (nicht auf den Zeigerwert, weil Postfix der Dereferenzierung Vorrang hat)

*++ptr - den Zeiger inkrementieren und dann dereferenzieren, da Präfix und Dereferenzierung die gleiche Priorität haben und daher in der Reihenfolge von rechts nach links ausgewertet werden

++*ptr - Ähnlich wie oben in Bezug auf die Rangfolge, wieder von rechts nach links, um den Zeiger dereferenzieren zu lassen und dann zu erhöhen, worauf der Zeiger zeigt. Bitte beachten Sie, dass dies in Ihrem Fall zu undefiniertem Verhalten führt, da Sie versuchen, eine schreibgeschützte Variable (char* p = "Hello";) zu ändern.

4
Nobilis

Ich werde mein Take hinzufügen, weil die anderen Antworten zwar richtig sind, aber ich denke, dass sie etwas vermissen.

 v = *ptr++

meint

 temp = ptr;
 ptr  = ptr + 1
 v    = *temp;

Wohingegen

 v = *++ptr

meint

 ptr = ptr + 1
 v   = *ptr

Es ist wichtig zu verstehen, dass das Post-Inkrement (und das Post-Decrement) bedeuten

 temp = ptr       // Temp created here!!!
 ptr  = ptr + 1   // or - 1 if decrement)
 v    = *temp     // Temp destroyed here!!!

Warum spielt es eine Rolle? Nun, in C ist das nicht so wichtig. In C++ kann ptr jedoch ein komplexer Typ wie ein Iterator sein. Zum Beispiel

 for (std::set<int>::iterator it = someSet.begin(); it != someSet.end(); it++)

Da it ein komplexer Typ ist, kann it++ in diesem Fall Nebenwirkungen aufgrund der temp-Erstellung haben. Wenn Sie Glück haben, wird der Compiler natürlich versuchen, nicht benötigten Code wegzuwerfen, aber wenn der Konstruktor oder der Destruktor des Iterators etwas tut, zeigt it++ diese Effekte, wenn er temp erstellt.

Das, was ich versuche zu sagen, ist Write What You Mean . Wenn Sie Inkrement ptr meinen, dann schreiben Sie ++ptr nicht ptr++. Wenn Sie temp = ptr, ptr += 1, temp meinen, schreiben Sie ptr++

3
gman
*ptr++    // 1

Das ist das Gleiche wie:

    tmp = *ptr;
    ptr++;

Der Wert des Objekts, auf den ptr zeigt, wird abgerufen, und ptr wird erhöht.

*++ptr    // 2

Das ist das Gleiche wie:

    ++ptr;
    tmp = *ptr;

Der Zeiger ptr wird also inkrementiert, dann wird das Objekt, auf das mit ptr gezeigt wird, gelesen.

++*ptr    // 3

Das ist das Gleiche wie:

    ++(*ptr);

Das Objekt, auf das ptr zeigt, wird inkrementiert. ptr selbst ist unverändert.

0
David R Tribble

postfix und Präfix haben also eine höhere Priorität als Dereferenzierung

* ptr ++ hier post inkrementieren ptr und dann auf neuen Wert von ptr verweisen

* ++ ptr hier Pre Increment Faust zeigt dann auf den neuen Wert von ptr

++ * ptr hier erhalten Sie zuerst den Wert von ptr, der auf diesen Wert zeigt, und erhöhen diesen Wert

0
Kiran Padwal

Zeigerausdrücke: * ptr ++, * ++ ptr und ++ * ptr:

Hinweis: Zeiger müssen initialisiert sein und eine gültige Adresse haben. Denn in RAM laufen neben unserem Programm (a.out) viel mehr Programme gleichzeitig, d. H. Wenn Sie versuchen, auf Speicher zuzugreifen, der nicht für Ihr Betriebssystem reserviert ist, liegt der Segmentierungsfehler vor.

Bevor wir dies erklären, betrachten wir ein einfaches Beispiel.

#include<stdio.h>
int main()
{
        int num = 300;
        int *ptr;//uninitialized pointer.. must be initialized
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr = *ptr + 1;//*ptr means value/data on the address.. so here value gets incremented
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        /** observe here that "num" got changed but manually we didn't change, it got modified by pointer **/
        ptr = ptr + 1;//ptr means address.. so here address got incremented
        /**     char pointer gets incremented by 1 bytes
          Integer pointer gets incremented by 4 bytes
         **/
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

analysieren Sie die Ausgabe des obigen Codes. Ich hoffe, Sie haben die Ausgabe des obigen Codes erhalten. Aus dem obigen Code wird deutlich, dass der Zeigername (ptr) bedeutet, dass es sich um Adresse handelt, und * ptr bedeutet, dass wir über abt Wert) sprechen/Daten.

CASE 1: * ptr ++, * ++ ptr, * (ptr ++) und * (++ ptr):

wie oben erwähnt, sind alle 4 Syntaxarten in allen address gets incremented ähnlich, aber wie die Adresse erhöht wird, ist anders.

Hinweis: Um einen Ausdruck zu lösen, ermitteln Sie, wie viele Operatoren im Ausdruck vorhanden sind, und suchen Sie dann Prioritäten des Operators. Mehrere Operatoren mit derselben Priorität überprüfen dann die Entwicklungsreihenfolge oder Assoziativität, die von rechts (R) nach links (L) oder von links nach rechts gehen können.

* ptr ++: Hier sind 2 Operatoren, nämlich De-Referenz (*) und ++ (Inkrement). Beide haben die gleiche Priorität und prüfen dann die Assoziativität, die von R nach L geht. Beginnen Sie also mit der Lösung von rechts nach links. 

* ptr ++: first ++ kam beim Lösen von R nach L, daher wird die Adresse inkrementiert, aber das Post-Inkrement.

* ++ ptr: Genau wie bei der ersten Adresse wird auch die Adresse inkrementiert, jedoch das vorherige Inkrement.

* (ptr ++): Hier gibt es 3 Operatoren, darunter grouping () mit der höchsten Priorität. Also wird zuerst ptr ++ gelöst, d. h. die Adresse wird erhöht, aber post.

* (++ ptr): Wie im obigen Fall wird auch die Adresse inkrementiert, aber vor Inkrement.

CASE 2: ++ * ptr, ++ (* ptr), (* ptr) ++:

wie oben erwähnt, sind alle 4 Syntaxarten in alle Werte/Daten werden inkrementiert ähnlich, aber wie sich der Wert ändert, unterscheidet sich.

++ * ptr: zuerst * kam beim Lösen von R nach L, daher wird der Wert geändert, aber sein Vor-Inkrement.

++ (* ptr): Wie im obigen Fall wird der Wert geändert.

(* ptr) ++: Hier gibt es 3 Operatoren, darunter grouping () mit der höchsten Priorität. Inside () * ptr ist da. Also wird zuerst * ptr gelöst, d. h. der Wert wird erhöht, aber post.

Hinweis: ++ * ptr und * ptr = * ptr + 1 sind beide gleich, in beiden Fällen wird der Wert geändert .. _. ++ * ptr: Es wird nur eine Anweisung (INC) verwendet, der Wert wird direkt in Einzelschuss geändert. * ptr = * ptr + 1: hier wird der erste Wert inkrementiert (INC) und dann zugewiesen (MOV). 

Um alle oben genannten unterschiedlichen Syntax der Inkrementierung auf Zeiger zu verstehen, kann einfacher Code betrachtet werden:

#include<stdio.h>
int main()
{
        int num = 300;
        int *ptr;
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//address changed(post increment), value remains un-changed
//      *++ptr;//address changed(post increment), value remains un-changed
//      *(ptr)++;//address changed(post increment), value remains un-changed
//      *(++ptr);//address changed(post increment), value remains un-changed

//      ++*ptr;//value changed(pre increment), address remains un-changed
//      (*ptr)++;//value changed(pre increment), address remains un-changed
//      ++(*ptr);//value changed(post increment), address remains un-changed

        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

Versuchen Sie im obigen Code, Kommentare zu kommentieren/entkommentieren und Ausgaben zu analysieren.

Zeiger als Konstante: Es gibt keine Möglichkeiten, wie Sie Zeiger als konstant machen können, wenige, die ich hier erwähne.

1) const int * p OR int const * p: Hier ist valuekonstant, Adresse ist nicht konstant dh wo p zeigt Einige Adresse Auf dieser Adresse, was ist der Wert? Ein Wert richtig? Ist dieser Wert konstant, kann dieser Wert nicht geändert werden, aber wo zeigt der Zeiger? Einige Adresse richtig? Es kann auch auf andere Adressen verweisen.

Um dies zu verstehen, betrachten wir folgenden Code:

#include<stdio.h>
int main()
{
        int num = 300;
        const int *ptr;//constant value, address is modifible
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//
//      *++ptr;//possible bcz you are trying to change address which is possible
//      *(ptr)++;//possible
//      *(++ptr);//possible

//      ++*ptr;//not possible bcz you trying to change value which is not allowed
//      (*ptr)++;//not possible
//      ++(*ptr);//not possible

        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

Versuchen Sie, die Ausgabe des obigen Codes zu analysieren

2) int const * p: es heißt '**constant pointe**r', d. H. address is constant but value is not constant. Hier dürfen Sie die Adresse nicht ändern, aber Sie können den Wert ändern.

Hinweis: Konstante Zeiger (über Fall) muss während der Deklaration selbst initialisiert werden.

Um dies zu verstehen, können Sie einfachen Code überprüfen.

#include<stdio.h>
int main()
{
        int x = 300;
        int* const p;
        p = &x;
        printf("x = %d p =%p and *p = %d\n",num,p,*p);
}

Wenn Sie in obigem Code feststellen, dass es keine ++ * p oder * p ++ gibt, denken Sie, dass dies ein einfacher Fall ist, da wir nicht die Adresse oder den Wert ändern, sondern Fehler erzeugen. Warum ? Grund, den ich in Kommentaren erwähne.

#include<stdio.h>
int main()
{
        int x = 300;
        /** constant pointer must initialize while decaring itself **/
        int* const p;//constant pointer i.e its pointing to some address(here its pointing to garbage), it should point to same address(i.e garbage ad
dress only 
        p = &x;// but here what we are doing ? we are changing address. we are making p to point to address of x instead of garbage address.
        printf("x = %d p =%p and *p = %d\n",num,p,*p);
}

Also, was ist die Lösung dieses Problems? 

     int* const p = &x;

weitere Informationen zu diesem Fall finden Sie unten.

#include<stdio.h>
int main()
{
        int num = 300;
        int *const ptr = &num;//constant value, address is modifible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//not possible
//      *++ptr;//not possible bcz you are trying to change address which is not possible
//      *(ptr)++;//not possible
//      *(++ptr);//not possible

//      ++*ptr;// possible bcz you trying to change value which is allowed
//      (*ptr)++;// possible
//      ++(*ptr);// possible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

3) const int * const p: Hier sowohl Adresse als auch Wert sind konstant

Um dies zu verstehen, können Sie den Code unten überprüfen

#include<stdio.h>
int main()
{
        int num = 300;
        const int* const ptr = &num;//constant value,constant address 
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//not possible
        ++*ptr;//not possible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}
0
Achal