Espressioni puntatore: * ptr ++, * ++ ptr e ++ * ptr


128

Di recente ho riscontrato questo problema che non riesco a capire da solo.

Cosa significano davvero queste tre espressioni ?

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

Ho provato Ritchie. Ma purtroppo non è stato in grado di seguire ciò che ha detto su queste 3 operazioni.

So che sono tutti eseguiti per incrementare il puntatore / il valore indicato. Posso anche immaginare che potrebbero esserci molte cose sulla precedenza e sull'ordine di valutazione. Come se uno aumentasse prima il puntatore, quindi recuperasse il contenuto di quel puntatore, uno semplicemente recuperasse il contenuto e quindi aumentasse il puntatore ecc. Ecc. Come potete vedere, non ho una chiara comprensione delle loro operazioni effettive , che vorrei cancellare al più presto. Ma sono davvero perso quando ho la possibilità di applicarli nei programmi. Per esempio:

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

mi dà questo risultato:

ello

Ma la mia aspettativa era che sarebbe stampato Hello. Un'ultima richiesta: ti prego di darmi degli esempi su come funziona ciascuna espressione in un determinato frammento di codice. Come la maggior parte delle volte, solo un semplice paragrafo della teoria mi viene sorpreso.


6
Hai perso la quarta: (*ptr)++(le parentesi dovevano essere *ptr++
chiare

15
Perché hai incrementato il puntatore prima di stamparlo. Volevi while (* p) e printf ("% c", * p ++);
dcaswell,

Grandi domande per l'intervista. Uso pratico limitato. Vorrei che C non avesse quei suggerimenti :)
Himanshu,

5
@Himanshu Se questo cuoce la pasta del tuo intervistato prova questo: Avere un puntatore globalechar* p , che punta a una stringa terminata valida di caratteri univoci. Quindi avere una funzione fn(char ch)che stampa sia il chparametro che il carattere corrente a cui punta p. Ora invoca fn(*p++);D: fnStampa lo stesso carattere due volte ? Saresti stupito da quanti professori sbagliano quella domanda.
WhozCraig,

1
poiché p indica una stringa letterale, dovresti scrivereconst char* p = "Hello";
hetepeperfan,

Risposte:


275

Ecco una spiegazione dettagliata che spero possa essere utile. Cominciamo con il tuo programma, in quanto è il più semplice da spiegare.

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

La prima affermazione:

const char* p = "Hello";

dichiara pcome puntatore a char. Quando diciamo "puntatore a char", cosa significa? Significa che il valore di pè l'indirizzo di a char; pci dice dove c'è nella memoria uno spazio riservato per contenere a char.

L'istruzione inoltre si inizializza pper indicare il primo carattere nella stringa letterale "Hello". Per il bene di questo esercizio, è importante capire pche punta non all'intera stringa, ma solo al primo carattere 'H',. Dopotutto, pè un puntatore a uno char, non all'intera stringa. Il valore di pè l'indirizzo di 'H'in "Hello".

Quindi imposta un loop:

while (*p++)

Cosa significa la condizione del loop *p++? Qui sono al lavoro tre cose che rendono questo enigma (almeno fino a quando non inizia la familiarità):

  1. La precedenza dei due operatori, postfix ++e indirection*
  2. Il valore di un'espressione di incremento postfix
  3. L'effetto collaterale di un'espressione di incremento postfix

1. Precedenza . Una rapida occhiata alla tabella delle precedenza per gli operatori ti dirà che l'incremento postfisso ha una precedenza più alta (16) rispetto a dereference / indirection (15). Ciò significa che il complesso espressione *p++sta per essere raggruppati come: *(p++). Vale a dire, la *parte verrà applicata al valore della p++parte. Quindi prendiamo p++prima la parte.

2. Valore dell'espressione Postfix . Il valore di p++è il valore di p prima dell'incremento . Se hai:

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

l'output sarà:

7
8

perché i++valuta iprima dell'incremento. Allo stesso modo p++sta per valutare il valore corrente di p. Come sappiamo, il valore corrente di pè l'indirizzo di 'H'.

Quindi ora la p++parte di *p++è stata valutata; è il valore corrente di p. Quindi la *parte accade. *(current value of p)significa: accedere al valore all'indirizzo di proprietà di p. Sappiamo che il valore a quell'indirizzo è 'H'. Quindi l'espressione *p++valuta 'H'.

Ora aspetta un minuto, stai dicendo. Se viene *p++valutato 'H', perché non viene 'H'stampato nel codice sopra? Ecco dove entrano in gioco gli effetti collaterali .

3. Effetti collaterali di espressione postfissa . Il postfisso ++ha il valore dell'operando corrente, ma ha l' effetto collaterale di incrementare quell'operando. Eh? Dai di nuovo un'occhiata a quel intcodice:

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

Come notato in precedenza, l'output sarà:

7
8

Quando i++viene valutato nella prima printf(), esso restituisce 7. Ma le garanzie C standard che ad un certo punto prima del secondo printf()inizia l'esecuzione, l' effetto collaterale del ++operatore avrà avuto luogo. Vale a dire, prima che printf()accada il secondo , isaranno stati incrementati come risultato ++dell'operatore nel primo printf(). Questo, tra l'altro, è una delle poche garanzie che lo standard offre sulla tempistica degli effetti collaterali.

Nel tuo codice, quindi, quando *p++viene valutata l'espressione , viene valutata 'H'. Ma quando arrivi a questo:

printf ("%c", *p)

quel fastidioso effetto collaterale si è verificato. pè stato incrementato. Whoa! Non punta più a 'H', ma al passato di un personaggio 'H': 'e'in altre parole. Questo spiega la tua produzione sconcertata:

ello

Da qui il coro di suggerimenti utili (e accurati) nelle altre risposte: per stampare la pronuncia ricevuta "Hello"e non la sua controparte cockney, hai bisogno di qualcosa di simile

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

Questo per quello. E il resto? Chiedete i significati di questi:

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

Abbiamo appena parlato del primo, quindi cerchiamo di guardare al secondo: *++ptr.

Abbiamo visto nella nostra precedente spiegazione che l'incremento postfisso p++ha una certa precedenza , un valore e un effetto collaterale . L'incremento del prefisso ++pha lo stesso effetto collaterale della sua controparte postfisso: incrementa il suo operando di 1. Tuttavia, ha una precedenza diversa e un valore diverso .

L'incremento del prefisso ha una precedenza inferiore rispetto al postfisso; ha la precedenza 15. In altre parole, ha la stessa precedenza dell'operatore dereference / indirection *. In un'espressione simile

*++ptr

ciò che conta non è la precedenza: i due operatori sono identici in precedenza. Quindi entra in gioco l' associatività . L'incremento del prefisso e l'operatore indiretto hanno associatività destra-sinistra. A causa di tale associatività, l'operando ptrverrà raggruppato con ++l'operatore più a destra prima dell'operatore più a sinistra *,. In altre parole, l'espressione verrà raggruppata *(++ptr). Quindi, come con *ptr++ma per un motivo diverso, anche qui la *parte verrà applicata al valore della ++ptrparte.

Quindi qual è quel valore? Il valore dell'espressione dell'incremento del prefisso è il valore dell'operando dopo l'incremento . Questo lo rende una bestia molto diversa dall'operatore di incremento postfix. Diciamo che hai:

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

L'output sarà:

8
8

... diverso da quello che abbiamo visto con l'operatore postfix. Allo stesso modo, se hai:

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

l'output sarà:

H e e l                // good dog

Capisci perché?

Ora arriviamo alla terza espressione hai chiesto, ++*ptr. Questo è il più complicato del lotto, in realtà. Entrambi gli operatori hanno la stessa precedenza e associatività destra-sinistra. Ciò significa che l'espressione verrà raggruppata ++(*ptr). La ++parte verrà applicata al valore della *ptrparte.

Quindi se abbiamo:

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

l'output sorprendentemente egotistico sarà:

I

Che cosa?! Va bene, quindi la *pparte sta per valutare 'H'. Quindi ++entra in gioco, a quel punto, verrà applicato al 'H', non al puntatore! Cosa succede quando aggiungi 1 a 'H'? Ottieni 1 più il valore ASCII di 'H', 72; ottieni 73. Rappresentalo come achar , e si ottiene il charcon il valore ASCII 73: 'I'.

Questo si prende cura delle tre espressioni che hai chiesto nella tua domanda. Eccone un altro, menzionato nel primo commento alla tua domanda:

(*ptr)++ 

Anche quello è interessante. Se hai:

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

ti darà questo risultato entusiasta:

HI

Cosa sta succedendo? Ancora una volta, è una questione di precedenza , valore di espressione ed effetti collaterali . A causa delle parentesi, la *pparte viene trattata come un'espressione primaria. Le espressioni primarie vincono tutto il resto; vengono valutati per primi. E *p, come sai, valuta 'H'. Il resto dell'espressione, la ++parte, viene applicato a quel valore. Quindi, in questo caso,(*p)++ diventa 'H'++.

Qual è il valore di 'H'++? Se hai detto 'I', hai dimenticato (già!) La nostra discussione sul valore rispetto all'effetto collaterale con incremento postfix. Ricorda, 'H'++valuta il valore corrente di 'H' . In modo che prima printf()verrà stampato 'H'. Quindi, come effetto collaterale , 'H'verrà incrementato 'I'. Il secondo lo printf()stampa 'I'. E hai il tuo saluto allegro.

Va bene, ma in questi ultimi due casi, perché ne ho bisogno

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

Perché non posso semplicemente avere qualcosa del genere

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

Perché "Hello"è una stringa letterale. Se ci provi ++*p, stai cercando di cambiare 'H'la stringa in 'I', creando l'intera stringa"Iello" . In C, i letterali stringa sono di sola lettura; il tentativo di modificarli invoca un comportamento indefinito. "Iello"è indefinito anche in inglese, ma è solo una coincidenza.

Al contrario, non puoi averlo

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

Perchè no? Perché in questo caso, pè un array. Un array non è un valore l modificabile; non puoi cambiare dovep punti in pre o post-incremento o decremento, poiché il nome dell'array funziona come se fosse un puntatore costante. (Non è quello che è in realtà; è solo un modo conveniente per vederlo.)

Per riassumere, ecco le tre cose che hai chiesto:

*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

Ed eccone un quarto, altrettanto divertente degli altri tre:

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

Il primo e il secondo andranno in crash se ptr realtà è un identificatore di array. Il terzo e il quarto andranno in crash se ptrpunta a una stringa letterale.

Ecco qua. Spero sia tutto cristallo adesso. Sei stato un grande pubblico e sarò qui tutta la settimana.


22
Prima di entrare in questo forum, ho cercato 3 libri "C" di cui sono proprietario. Ho anche provato alcuni notevoli tutorial online. Ma nessuno di loro si avvicina alla tua spiegazione (specialmente il modo in cui hai messo tutto insieme). Non hai solo risposto alla domanda che ho posto, ma hai anche discusso molte più cose dal livello di base. In realtà oggi mi hai insegnato molte cose di base, che prima mi mancavano. Non ho potuto fare a meno di alternare la mia risposta accettata. :) Grazie ancora.
assegnato il

26
+1 Penso che questa sia la migliore risposta lunga che ho letto su SO. Penso che tutti possano imparare molto da questa risposta.
Shafik Yaghmour,

9
Signore, dovrei scrivere un libro su C.
Dillon Burton il

1
Che bella risposta a una buona domanda! Ben fatto @verbose!
benka,

7
@verbose signore, siete stati all'altezza del vostro nome .. :)
sleeping_dragon

44

Supponiamo che ptrpunti all'i-esimo elemento dell'array arr.

  1. *ptr++valuta arr[i]e imposta ptrper puntare all'elemento (i + 1) di arr. È equivalente a *(ptr++).

  2. *++ptrimposta ptrper puntare all'elemento (i + 1) -th di arre valuta arr[i+1]. È equivalente a *(++ptr).

  3. ++*ptraumenta arr[i]di uno e valuta il suo valore aumentato; il puntatore non ptrviene toccato. È equivalente a ++(*ptr).

Ne esiste anche un altro, ma per scriverlo avrai bisogno di parentesi:

  1. (*ptr)++aumenta arr[i]di uno e valuta il suo valore prima di essere aumentato; il puntatore ptrrimane di nuovo intatto.

Il resto lo puoi capire tu stesso; ha anche risposto @Jaguar.


13

*ptr++ : post increment a pointer ptr

*++ptr : Pre Increment a pointer ptr

++*ptr : preincrement the value at ptr location

Leggi qui gli operatori pre-incremento e post-incremento


Questo darà Hellocome output

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

@ Nik-Lz Sì, l'uscita sarebbeHello
Jainendra,

7

La condizione nel tuo ciclo è cattiva:

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

Equivale a

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

E questo è sbagliato, questo dovrebbe essere:

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

*ptr++è lo stesso di *(ptr++), che è:

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

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

*++ptrè lo stesso di *(++ptr), che è:

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

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

++*ptrè lo stesso di ++(*ptr), che è:

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

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

Sono assolutamente d'accordo con la prima parte della risposta. Nella seconda parte, l'inizializzazione dei puntatori (ai numeri interi!) Con i numeri interi è fonte di confusione per qualcuno che sta lottando per comprendere l'utilizzo dei puntatori.
Nickie,

4

Hai ragione sulla precedenza, nota che *ha la precedenza sull'incremento del prefisso, ma non sull'incremento del postfisso. Ecco come questi guasti:

*ptr++ - andando da sinistra a destra, dereference il puntatore, quindi incrementa il valore del puntatore (non quello a cui punta, a causa della precedenza di postfix su dereference)

*++ptr - incrementa il puntatore e poi lo dereference, questo perché prefisso e dereference hanno la stessa precedenza e quindi vengono valutati in ordine da destra a sinistra

++*ptr- simile al precedente in termini di precedenza, passando di nuovo da destra a sinistra per differenziare il puntatore e quindi incrementare ciò a cui punta il puntatore. Si noti che nel tuo caso questo porterà a un comportamento indefinito perché stai cercando di modificare una variabile di sola lettura ( char* p = "Hello";).


3

Aggiungerò la mia opinione perché, mentre le altre risposte sono corrette, penso che manchi qualcosa.

 v = *ptr++

si intende

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

Mentre

 v = *++ptr

si intende

 ptr = ptr + 1
 v   = *ptr

È importante capire che significa post increment (e post decrement)

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

Perchè importa? Bene in C non è così importante. In C ++ ptrpotrebbe essere un tipo complesso come un iteratore. Per esempio

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

In questo caso, perché itè un tipo complesso it++potrebbe avere effetti collaterali a causa della tempcreazione. Naturalmente se sei fortunato il compilatore proverà a buttare via il codice non necessario ma se il costruttore o il distruttore dell'iteratore fa qualcosa, it++mostrerà quegli effetti quando createmp .

Il corto di ciò che sto cercando di dire è Scrivi cosa vuoi dire . Se intendi increment ptr, allora ++ptrnon scrivere ptr++. Se vuoi dire temp = ptr, ptr += 1, tempallora scriviptr++


0
*ptr++    // 1

Questo è lo stesso di:

    tmp = *ptr;
    ptr++;

Quindi ptrviene recuperato il valore dell'oggetto indicato da , quindi ptrviene incrementato.

*++ptr    // 2

Questo è lo stesso di:

    ++ptr;
    tmp = *ptr;

Quindi il puntatore ptrviene incrementato, quindi ptrviene letto l'oggetto a cui punta .

++*ptr    // 3

Questo è lo stesso di:

    ++(*ptr);

Quindi l'oggetto a cui punta ptrviene incrementato; ptrstesso è invariato.


0

postfisso e prefisso hanno una precedenza più alta rispetto alla dereferenza

* ptr ++ qui post incrementa ptr e quindi punta al nuovo valore di ptr

* ++ ptr qui Pugno pre-incremento, quindi punta al nuovo valore di ptr

++ * ptr qui prima ottiene il valore di ptr che punta a e incrementa quella vlaue


1
Questo non è corretto Postfix ha una precedenza più alta, ma il prefisso ha la stessa precedenza di dereference.
verboso

0

Espressioni puntatore: * ptr ++, * ++ ptr e ++ * ptr:

Nota : i puntatori devono essere inizializzati e devono avere un indirizzo valido. Perché nella RAM oltre al nostro programma (a.out) ci sono molti più programmi in esecuzione contemporaneamente, ad esempio se si tenta di accedere ad una memoria che non è stata riservata per il sistema operativo, si verifica un errore di segmentazione.

Prima di spiegare questo, consideriamo un semplice esempio?

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

analizzare l'output del codice sopra, spero che tu abbia l'output del codice sopra. Una cosa è chiara dal codice sopra è che il nome del puntatore ( ptr ) significa che stiamo parlando di indirizzo e * ptr significa che stiamo parlando di valore / dati.

CASO 1 : * ptr ++, * ++ ptr, * (ptr ++) e * (++ ptr):

sopra menzionate tutte e 4 le sintassi sono simili, in tutto address gets incrementedma come viene incrementato l'indirizzo è diverso.

Nota : per risolvere qualsiasi espressione scopri quanti operatori ci sono in espressione, quindi scopri le priorità dell'operatore. I più operatori con la stessa priorità controllano quindi l'ordine di evoluzione o associatività che può destra (R) a sinistra (L) o sinistra a destra.

* ptr ++ : qui ci sono 2 operatori, ovvero de-reference (*) e ++ (incremento). Entrambi hanno la stessa priorità, quindi controlla l'associatività che va da R a L. Quindi inizia a risolvere da destra a sinistra, qualunque sia l'operatore che arriva per primo.

* ptr ++ : il primo ++ è arrivato durante la risoluzione da R a L, quindi l'indirizzo viene incrementato ma il suo incremento post.

* ++ ptr : uguale al primo qui anche l'indirizzo viene incrementato ma il suo pre-incremento.

* (ptr ++) : qui ci sono 3 operatori, tra cui il raggruppamento () che ha la massima priorità, quindi prima ptr ++ risolto cioè l'indirizzo viene incrementato ma post.

* (++ ptr) : come nel caso precedente, anche l'indirizzo viene incrementato ma pre-incrementato.

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

sopra menzionato tutte e 4 le sintassi sono simili, in tutto il valore / i dati vengono incrementati ma come il valore viene cambiato è diverso.

++ * ptr : il primo * è arrivato durante la risoluzione da R a L, quindi il valore viene modificato ma il suo pre-incremento.

++ (* ptr) : come nel caso precedente, il valore viene modificato.

(* ptr) ++ : qui ci sono 3 operatori, tra cui il raggruppamento () con la massima priorità, Inside () * ptr è lì, quindi il primo * ptr è risolto ovvero il valore viene incrementato ma post.

Nota : ++ * ptr e * ptr = * ptr + 1 sono entrambi uguali, in entrambi i casi il valore viene modificato. ++ * ptr: viene utilizzata solo 1 istruzione (INC), il valore viene modificato direttamente in un singolo colpo. * ptr = * ptr + 1: qui il primo valore viene incrementato (INC) e quindi assegnato (MOV).

Per comprendere sopra la diversa sintassi dell'incremento sul puntatore, prendiamo in considerazione un semplice codice:

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

Nel codice sopra, prova a commentare / annullare il commento e analizzare gli output.

Puntatori come costanti : non ci sono modi in cui è possibile rendere i puntatori come costanti, pochi ne citerò qui.

1) const int * p OR int const * p : qui valueè costante , l' indirizzo non è costante, ovvero dove p sta puntando? Qualche indirizzo? Su quell'indirizzo qual è il valore? Qualche valore giusto? Quel valore è costante, non puoi modificarlo ma dove punta il puntatore? Qualche indirizzo giusto? Può indicare anche un altro indirizzo.

Per capire questo, prendiamo in considerazione il codice seguente:

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

Prova ad analizzare l'output del codice sopra

2) int const * p : si chiama ' **constant pointe**r' ie address is constant but value is not constant. Qui non ti è permesso cambiare l'indirizzo ma puoi modificare il valore.

Nota : il puntatore costante (sopra il caso) deve essere inizializzato mentre si declariung stesso.

Per capire questo, controlla il codice semplice.

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

Nel codice sopra, se osservi che non c'è ++ * p o * p ++ Quindi potresti pensare che questo sia un caso semplice perché non stiamo cambiando indirizzo o valore ma produrrà un errore. Perché ? Motivo che menziono nei commenti.

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

Qual è la soluzione di questo problema?

     int* const p = &x;

per ulteriori informazioni su questo caso, consideriamo l'esempio seguente.

#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 : qui sia l'indirizzo che il valore sono costanti .

Per capirlo, controlla sotto il codice

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

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

++*psignifica che stai tentando di incrementare il valore ASCII di *pcui

   is "Hello"
       ^
       | 
       p

non è possibile incrementare il valore perché è una costante in modo da ottenere un errore

per quanto riguarda il tuo ciclo while, il ciclo continua fino a *p++raggiungere la fine della stringa in cui è presente un carattere '\0'(NULL).

Ora, poiché *p++salta il primo carattere, otterrai l'output solo a partire dal secondo carattere.

Il codice seguente non produrrà nulla perché while loop ha '\0'

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

Il codice seguente ti darà lo stesso output del codice successivo, cioè ello.

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

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

const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.