Wyrażenia wskaźnikowe: * ptr++, * ++ptr i ++ * ptr

[4]}ostatnio natknąłem się na ten problem, którego sam nie jestem w stanie zrozumieć.

Co te trzy wyrażenia naprawdę oznaczają?

*ptr++
*++ptr
++*ptr
Próbowałem Ritchie ' ego. Ale niestety nie był w stanie śledzić tego, co powiedział o tych trzech operacjach.

Wiem, że wszystkie są wykonywane w celu zwiększenia wskaźnika / wartości wskazywanej. Mogę również domyślać się, że może być wiele rzeczy na temat pierwszeństwa i kolejności oceny. Jak jeden zwiększa wskaźnik najpierw wtedy pobiera zawartość tego wskaźnika, po prostu pobiera zawartość, a następnie zwiększa wskaźnik itd itd. Jak widzisz, nie mam jasnego zrozumienia ich operacji , które chciałbym jak najszybciej wyjaśnić. Ale jestem naprawdę zagubiony, gdy mam szansę zastosować je w programach. Na przykład:

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

Daje mi to wyjście:

ello

Ale oczekiwałem, że to wydrukuje Hello . Ostatnia Prośba-proszę podać mi przykłady jak każdy wyrażenie działa w danym fragmencie kodu. Przez większość czasu nad moją głową przelatuje tylko jeden akapit teorii.

Author: Jarod42, 2013-08-28

10 answers

Oto szczegółowe wyjaśnienie, które mam nadzieję będzie pomocne. Zacznijmy od Twojego programu, ponieważ jest najprostszy do wyjaśnienia.

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

Pierwsza wypowiedź:

const char* p = "Hello";

Deklaruje p jako wskaźnik do char. Kiedy mówimy " wskaźnik do char", co to znaczy? Oznacza to, że wartość p jest adresem char; p mówi nam, gdzie w pamięci jest trochę miejsca na char.

Twierdzenie inicjalizuje również p do wskaż pierwszy znak w łańcuchu znaków "Hello". Ze względu na to ćwiczenie, ważne jest, aby zrozumieć p jako wskazywanie Nie całego ciągu, ale tylko pierwszego znaku, 'H'. W końcu p jest wskaźnikiem do jednego char, a nie do całego łańcucha. Wartość p jest adresem 'H' W "Hello".

Następnie ustawiasz pętlę:

while (*p++)

Co oznacza warunek pętli *p++? Działają tu trzy rzeczy, które sprawiają, że jest to zagadkowe (w najmniej do momentu wprowadzenia znajomości):

    W przeciwieństwie do innych operatorów, postfix nie może być używany w innych operacjach.]} Nie jest to jednak możliwe, ponieważ nie jest to możliwe.]}
  1. efekt uboczny wyrażenia przyrostowego postfix

1. Pierwszeństwo . Szybki rzut oka na tabelę pierwszeństwa operatorów powie Ci, że przyrost postfixa ma wyższy priorytet (16) niż dereference / indirection (15). Oznacza to, że kompleks wyrażenie *p++ będzie zgrupowane jako: *(p++). Oznacza to, że część * zostanie zastosowana do wartości części p++. Więc weźmy najpierw część p++.

2. Wartość wyrażenia Postfix . Wartość p++ jest wartością p przed przyrostem . Jeśli masz:

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

Wyjście będzie:

7
8

Ponieważ i++ ocenia na i przed przyrostem. Podobnie p++ będzie oceniać do obecnego wartość p. Jak wiemy, bieżącą wartością p jest adres 'H'.

Więc teraz p++ część *p++ została oceniona; jest to aktualna wartość p. Potem następuje * część. *(current value of p) oznacza: dostęp do wartości pod adresem p. Wiemy, że wartość pod tym adresem to 'H'. Tak więc wyrażenie *p++ ewaluuje do 'H'.

/ Align = "left" / Jeśli *p++ ocenia na 'H', dlaczego 'H' nie wyświetla się w powyższy kod? Tutaj pojawiają się efekty uboczne.

3. Efekty uboczne ekspresji postfixa . Postfix ++ ma wartość bieżącego operandu, ale ma efekt uboczny zwiększania tego operandu. Co? Spójrz na ten kod int jeszcze raz:

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

Jak wspomniano wcześniej, wyjście będzie:

7
8

Gdy i++ jest oceniana w pierwszym printf(), ocenia się do 7. Ale standard C gwarantuje, że w w pewnym momencie przed rozpoczęciem wykonywania drugiego printf(), nastąpi efekt uboczny operatora++. Oznacza to, że zanim nastąpi drugi printf(), i zostanie zwiększony w wyniku ++ operatora w pierwszym printf(). To, nawiasem mówiąc, jest jedną z niewielu gwarancji, które standard daje o czasie skutków ubocznych.

W Twoim kodzie, następnie, gdy wyrażenie *p++jest oceniane, ocenia się na 'H'. Ale zanim dojdziesz do to:

printf ("%c", *p)

To nieprzyjemne skutki uboczne wystąpiły. p został zwiększony. Whoa! Nie wskazuje już na 'H', ale na jeden znak przeszłości 'H': na 'e', innymi słowy. To wyjaśnia Twoje cockneyowskie wyjście:

ello

Stąd refren przydatnych (i dokładnych) sugestii w innych odpowiedziach: aby wydrukować otrzymaną wymowę "Hello", a nie jej odpowiednik cockney, potrzebujesz czegoś w rodzaju {138]}

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

To by było na tyle. A co z resztą? Ty zapytaj o ich znaczenia:

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

Właśnie rozmawialiśmy o pierwszym, więc spójrzmy na drugi: *++ptr.

Widzieliśmy w naszym wcześniejszym wyjaśnieniu, że przyrost postfix p++ ma pewien pierwszeństwo, wartość i efekt uboczny. Przedrostek increment ++p ma ten sam efekt uboczny jak jego odpowiednik postfix: zwiększa jego operand o 1. Jednak ma inny pierwszeństwo i inny wartość .

Przyrost przedrostka ma niższy priorytet niż postfix; ma pierwszeństwo 15. Innymi słowy, ma taki sam priorytet jak operator dereference / indirection *. W wyrażeniu typu

*++ptr

Nie liczy się pierwszeństwo: dwa operatory są identyczne w pierwszeństwie. Więc Asocjacja zaczyna działać. Prefiks increment i operator indirection mają asocjację od prawej do lewej. Z powodu tej asocjacji, operand ptr będzie grupowany z operatorem po prawej stronie ++ przed operatorem bardziej po lewej stronie, *. Innymi słowy, wyrażenie będzie zgrupowane *(++ptr). Tak jak w przypadku *ptr++, ale z innego powodu, również tutaj część * zostanie zastosowana do wartości ++ptr.

Więc jaka jest ta wartość? Wartość wyrażenia przyrostkowego jest wartością argumentu po przyrostku. To sprawia, że jest to bardzo inna bestia od operator przyrostu postfixa. Powiedzmy, że masz:

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

Wyjście będzie:

8
8

... różni się od tego, co widzieliśmy z operatorem postfix. Podobnie, jeśli masz:

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++

Wyjście będzie:

H e e l                // good dog

Widzisz dlaczego?

Teraz przejdziemy do trzeciego wyrażenia, o które pytałeś, ++*ptr. Właściwie to najtrudniejsza z tych rzeczy. Oba operatory mają ten sam priorytet i asocjację od prawej do lewej. Oznacza to wyrażenie będą zgrupowane ++(*ptr). Część ++ zostanie zastosowana do wartości części *ptr.

Więc jeśli mamy:

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

Zaskakująco egoistyczny wynik będzie:

I
Co?! OK, więc część *p będzie oceniana do 'H'. Wtedy ++ wchodzi w grę, w którym momencie, to będzie stosowane do 'H', a nie do wskaźnika w ogóle! Co się stanie, gdy dodasz 1 do 'H'? Otrzymasz 1 plus wartość ASCII 'H', 72; otrzymasz 73. Reprezentuj to jako char, a otrzymasz char z wartością ASCII 73: 'I'.

To zajmuje się trzema wyrażeniami, o które pytałeś w swoim pytaniu. Oto kolejny, wspomniany w pierwszym komentarzu do twojego pytania:

(*ptr)++ 
To też jest interesujące. Jeśli masz:
char q[] = "Hello";
char* p = q;
printf ("%c", (*p)++);
printf ("%c\n", *p);

Da ci to entuzjastyczne wyjście:

HI
Co się dzieje? Ponownie, to kwestia pierwszeństwa, wartość wyrażenia , i skutki uboczne . Ze względu na nawiasy część *p jest traktowana jako wyrażenie podstawowe. Podstawowe wyrażenia przewyższają wszystko inne; są najpierw oceniane. I *p, jak wiesz, ocenia do 'H'. Reszta wyrażenia, część ++, zostanie zastosowana do tej wartości. W tym przypadku (*p)++ staje się 'H'++.

Jaka jest wartość 'H'++? Jeśli powiedziałeś 'I', zapomniałeś (już !) nasza dyskusja na temat wartości a efekt uboczny z postfixem przyrost. Pamiętaj, 'H'++ ocenia do bieżącej wartości 'H'. Tak więc pierwszy {[73] } zostanie wydrukowany 'H'. Następnie, jako efekt uboczny , to 'H' zostanie zwiększona do 'I'. Drugi printf() drukuje 'I'. I masz swoje radosne pozdrowienia.

W porządku, ale w tych dwóch ostatnich przypadkach, po co mi to]}
char q[] = "Hello";
char* p = q;

Dlaczego nie mogę mieć czegoś takiego

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

Ponieważ "Hello" jest ciągiem literalnym. Jeśli spróbujesz ++*p, próbujesz zmienić 'H' w łańcuchu na 'I', tworząc cały łańcuch "Iello". W języku C literały łańcuchów są tylko do odczytu; próba ich modyfikacji wywołuje niezdefiniowane zachowanie. "Iello" jest niezdefiniowany również w języku Angielskim, ale to tylko zbieg okoliczności.

Odwrotnie, nie możesz mieć

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

Dlaczego nie? Ponieważ w tym przypadku p jest tablicą. Tablica nie jest modyfikowalną wartością l; nie można zmienić gdzie p punktów przez pre - lub post-increment lub dekrementacja, ponieważ nazwa tablicy działa tak, jakby była stałym wskaźnikiem. (To nie jest to, co jest w rzeczywistości; to jest po prostu wygodny sposób, aby na to spojrzeć.)

Podsumowując, oto trzy rzeczy, o które zapytałeś:

*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

I tu jest czwarty, co nieco tak samo zabawny jak pozostałe trzy:

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

Pierwszy i drugi ulegną awarii, jeśli ptr jest identyfikatorem tablicy. Trzecia i czwarta ulegnie awarii, jeśli ptr wskaże na literalny ciąg znaków.

Proszę bardzo. Mam nadzieję, że teraz wszystko jest kryształowe. Byliście wspaniałą publicznością, a ja będę tu cały tydzień.
 229
Author: verbose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-10 13:16:16

Załóżmy, że ptr wskazuje na i-ten element tablicy arr.

  1. *ptr++ ocenia do arr[i] i ustawia ptr, aby wskazać (i+1)-Ten element arr. Jest odpowiednikiem *(ptr++).

  2. *++ptr ustawia ptr, aby wskazać (i+1)-Ten element arr i ewaluuje do arr[i+1]. Jest odpowiednikiem *(++ptr).

  3. ++*ptr zwiększa arr[i] o jeden i ocenia do jego zwiększonej wartości; wskaźnik {[0] } pozostaje nietknięty. Jest to równoważne ++(*ptr).

Jest jeszcze jeden, ale trzeba by nawiasy napisać:

  1. (*ptr)++ zwiększa arr[i] o jeden i ocenia do jego wartości przed zwiększeniem; wskaźnik ptr pozostaje ponownie nietknięty.

Resztę możesz sam wymyślić; na to też odpowiedział @Jaguar.

 42
Author: nickie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-28 07:44:21

*ptr++ : post increment a pointer ptr

*++ptr : Pre Increment a pointer ptr

++*ptr : preincrement the value at ptr location

Przeczytaj tutaj o operatorach Pre increment i post increment


To da Hello jako wyjście

int main()
{
    const char *p = "Hello";
    while(*p)
         printf("%c",*p++);//Increment the pointer here 
    return 0;
}
 13
Author: Jainendra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-10 03:49:17

Stan w Twojej pętli jest zły:

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

Jest tym samym co

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

I to jest złe, to powinno być:

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

*ptr++ jest tym samym co *(ptr++), czyli:

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

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

*++ptr jest tym samym co *(++ptr), czyli:

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

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

++*ptr jest tym samym co ++(*ptr), czyli:

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

value = *ptr;
++value;
printf("%c", value); // will print 'f' ('e' + 1)
 7
Author: nouney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-10 13:17:54

Masz rację co do pierwszeństwa, zauważ, że {[0] } ma pierwszeństwo przed przyrostkiem, ale nie przed przyrostkiem postfixa. Oto jak te załamania:

*ptr++ - idąc od lewej do prawej, dereferencja wskaźnika, a następnie zwiększenie wartości wskaźnika (nie to, co wskazuje, ze względu na pierwszeństwo postfixa nad dereferencją)

*++ptr - zwiększ wskaźnik, a następnie dereferencję, dzieje się tak dlatego, że prefix i dereferencja mają ten sam priorytet i dlatego są oceniane w kolejność od prawej do lewej

++*ptr - podobnie jak powyżej w zakresie pierwszeństwa, ponownie przechodząc od prawej do lewej w celu dereferencji wskaźnik, a następnie zwiększyć to, co wskazuje wskaźnik. Zwróć uwagę, że w Twoim przypadku będzie to prowadzić do niezdefiniowanego zachowania, ponieważ próbujesz zmodyfikować zmienną tylko do odczytu (char* p = "Hello";).

 4
Author: Nobilis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-28 07:38:21

Dodam moje zdanie, ponieważ o ile inne odpowiedzi są poprawne, to myślę, że czegoś im brakuje.

 v = *ptr++

Oznacza

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

Gdzie jako

 *++ptr

Oznacza

 ptr = ptr + 1
 v   = *ptr
Ważne jest, aby zrozumieć, że post increment (i post decrement) oznacza
 temp = ptr       // Temp created here!!!
 ptr  = ptr + 1   // or - 1 if decrement)
 v    = *temp     // Temp destroyed here!!!

Dlaczego to ma znaczenie? W C to nie jest takie ważne. W C++ choć ptr może być typem złożonym jak iterator. Na przykład

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

W tym przypadku, ponieważ it jest złożonym typ it++ może mieć skutki uboczne ze względu na tworzenie temp. Oczywiście, jeśli masz szczęście, kompilator spróbuje wyrzucić kod, który nie jest potrzebny, ale jeśli konstruktor lub Destruktor iteratora coś zrobi, to it++ pokaże te efekty podczas tworzenia temp.

Krótki z tego co próbuję powiedzieć to napisz co masz na myśli . Jeśli masz na myśli przyrost ptr to napisz ++ptr a nie ptr++. Jeśli masz na myśli temp = ptr, ptr += 1, temp to napisz ptr++

 2
Author: gman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-28 13:08:20

Postfix i prefiks mają wyższy priorytet niż dereferencja, więc

*ptr++ tutaj post increment ptr a następnie wskazanie nowej wartości ptr

* ++ptr tutaj Pre inkrementuj pięść, a następnie wskaż nową wartość ptr

++ * ptr tutaj najpierw uzyskaj wartość ptr wskazującą i zwiększającą, że vlaue

 1
Author: Kiran Padwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-10 05:36:55
*ptr++    // 1

To jest to samo co:

    tmp = *ptr;
    ptr++;

Tak więc wartość obiektu wskazywanego przez ptr jest pobierana, a następnie ptr jest zwiększana.

*++ptr    // 2

To jest to samo co:

    ++ptr;
    tmp = *ptr;

Zatem wskaźnik ptr jest zwiększany, a następnie odczytywany jest obiekt wskazywany przez ptr.

++*ptr    // 3

To jest to samo co:

    ++(*ptr);

Tak więc obiekt wskazywany przez ptr jest zwiększany; ptr sam w sobie pozostaje niezmieniony.

 0
Author: David R Tribble,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-04 00:05:55

Wyrażenia wskaźnikowe: * ptr++, * ++ptr i ++ * ptr:

Notatka: wskaźniki muszą być zainicjalizowane i muszą mieć poprawny adres. Ponieważ w pamięci RAM oprócz naszego programu (a. out) jest o wiele więcej programów działających jednocześnie tj. jeśli próbujesz uzyskać dostęp do pamięci, która nie była zarezerwowana dla Ciebie System operacyjny będzie przez segmentację usterki.

Zanim to wyjaśnimy rozważmy prosty przykład ?

#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);
}

Analizuj wyjście powyższego kodu, mam nadzieję, że masz wyjście powyższego kodu. Z powyższego kodu wynika jedno, że nazwa wskaźnika (ptr ) oznacza, że mówimy o adresie i * ptr oznacza, że mówimy o abbout value /data.

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

Wyżej wymienione wszystkie 4 składnie są podobne, we wszystkich address gets incremented ale jak adres jest zwiększany, to jest inaczej.

Uwaga : do rozwiązywania dowolnych wyrażeń dowiedz się jak wiele operatorów znajduje się w wyrażeniu, a następnie dowiadujemy się o priorytetach operatora. I wiele operatorów o tym samym priorytecie, a następnie sprawdzić kolejność ewolucji lub Asocjacja, które mogą od prawej (R) do lewej (L) ot od lewej do prawej.

*ptr++: tutaj są dwa operatory, mianowicie de-reference ( * ) i ++(increment). Oba mają ten sam priorytet, a następnie sprawdź asocjację, która jest od R do L. więc zaczyna rozwiązywać od prawej do lewej, niezależnie od operatorów nadchodzi pierwszy.

*ptr++: pierwszy ++ przyszedł podczas rozwiązywania z R do L, więc adres jest zwiększany, ale jego przyrost post.

*++ptr: tak samo jak pierwszy tutaj również adres jest inkrementowany, ale jego przed inkrementem.

*(ptr++) : tutaj są 3 operatory, wśród nich grouping () o najwyższym priorytecie, więc pierwszy PTR++ rozwiązany tzn. adres zostanie zwiększony, ale post.

*(++ptr) : tak samo jak powyzszy przypadek tutaj tez adres dostaje incremented ale Pre increment.

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

Wyżej wymienione wszystkie 4 składnie są podobne, w wszystkie wartości / dane są zwiększane ale jak zmienia się wartość, to jest inaczej.

++*ptr : pierwsze * przyszło podczas rozwiązywania z R do L, więc wartość jest zmieniana, ale jej przedrostek.

++(*ptr) : tak samo jak powyżej, wartość jest modyfikowana.

(*ptr)++: tutaj są 3 operatory, wśród nich grouping () o najwyższym priorytecie, wewnątrz () * ptr jest tam, więc pierwszy * ptr jest rozwiązany, tzn. wartość jest zwiększana, ale post.

Uwaga : ++ * ptr i *ptr = * ptr + 1 są takie same, w obu przypadkach wartość jest zmieniana. ++ * ptr: używana jest tylko 1 Instrukcja (INC), bezpośrednio wartość jest zmieniana w jednym strzale. * ptr = * ptr + 1: tutaj pierwsza wartość zostanie zwiększona (INC), a następnie przypisana (MOV).

Aby zrozumieć wszystkie powyższe różne składnie przyrost na wskaźniku pozwala rozważyć prosty kod:

#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);
}

W powyższym kodzie spróbuj komentować / komentować komentarze i analizować wyniki.

Wskaźniki jako stałe : nie ma sposobów, za pomocą których można zrobić wskaźniki jako stałe, kilka wspominam tutaj.

1)const int * P lub int const * p : tutaj value jest stałą, adres nie jest stały czyli gdzie p wskazuje ? Jakiś adres ? Pod tym adresem jaka jest wartość ? Jakaś wartość, PRAWDA ? Wartość ta jest stała, nie można zmodyfikować tej wartości, ale gdzie wskaźnik jest wskazywany ? Jakiś adres, prawda ? Może również wskazywać na inny adres.

Aby to zrozumieć rozważmy poniższy kod:

#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);
}

Spróbuj przeanalizować wyjście powyższego kodu

2)int const * p: nazywa się "**constant pointe**r " tzn. address is constant but value is not constant. Tutaj nie możesz zmienić adresu, ale możesz zmodyfikować wartość.

Uwaga : stały wskaźnik (powyżej) musi initialize while declaration itself.

Aby to zrozumieć, sprawdźmy prosty kod.

#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);
}

W powyższym kodzie, jeśli zauważysz, że nie ma ++ * p lub * P++, więc możesz pomyśleć, że jest to prosty przypadek, ponieważ nie zmieniamy adresu ani wartości, ale spowoduje to błąd. Dlaczego ? Powód, o którym wspominam w komentarzach.

#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);
}

Więc jakie jest rozwiązanie tego problemu ?

     int* const p = &x;

Aby dowiedzieć się więcej o tym przypadku, rozważmy poniższy przykład.

#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 : tutaj zarówno adres, jak i wartość są stałymi.

Aby to zrozumieć, sprawdźmy poniższy kod

#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
Author: Achal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-04 13:24:53
const char *p = "Hello";   

*p means "Hello"
          ^
          | 
          p

*p++ means "Hello"
             ^
             | 
             p

*++p means "Hello"
            ^
            |     (WHILE THE STATEMENT IS EXECUTED)
            p

*++p means "Hello"
             ^
             |     (AFTER THE STATEMENT IS EXECUTED)
             p

++*p oznacza, że próbujesz zwiększyć wartość ASCII *p, która

   is "Hello"
       ^
       | 
       p

Nie możesz zwiększyć wartości, ponieważ jest to stała, więc otrzymasz błąd

Jeśli chodzi o pętlę while, pętla biegnie aż *p++ dotrze do końca łańcucha, gdzie znajduje się znak '\0' (NULL).

Teraz, ponieważ *p++ pomija pierwszy znak, można uzyskać tylko wyjście począwszy od drugiego znaku.

Poniższy kod nie będzie wyświetlany wszystko ponieważ pętla while ma '\0'

const char *p = "Hello";
    while('\0') 
         printf("%c",*p);

Poniższy kod daje taki sam wynik jak następny kod, czyli ello .

const char *p = "Hello";
    while(*++p)
         printf("%c",*p);

...................................

const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
 -1
Author: iammosespaulr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-11 17:23:14