Expressões de ponteiro: * ptr ++, * ++ ptr e ++ * ptr

128

Recentemente, deparei-me com este problema que não consigo entender sozinho.

O que essas três expressões realmente significam?

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

Eu tentei Ritchie. Infelizmente, porém, não foi possível acompanhar o que ele disse sobre essas três operações.

Eu sei que todos eles são executados para incrementar o ponteiro / valor apontado. Também posso supor que possa haver muitas coisas sobre precedência e ordem de avaliação. Como um incrementos o ponteiro do primeiro, em seguida, obtém o conteúdo desse ponteiro, simplesmente busca o conteúdo e, em seguida, incrementa o ponteiro etc etc. Como você pode ver, eu não tenho uma compreensão clara sobre os seus reais operações, que eu gostaria de limpar o mais rápido possível. Mas estou verdadeiramente perdido quando tenho a chance de aplicá-los em programas. Por exemplo:

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

me dá esta saída:

ello

Mas minha expectativa era que fosse impressa Hello. Uma solicitação final - dê-me exemplos de como cada expressão funciona em um determinado snippet de código. Como na maioria das vezes, apenas um mero parágrafo da teoria passa pela minha cabeça.

alocado
fonte
6
Você perdeu a quarta: (*ptr)++(parênteses necessário para disambiguate de *ptr++)
user4815162342
15
Porque você incrementou o ponteiro antes de imprimi-lo. Você queria while (* p) e printf ("% c", * p ++);
dcaswell
Ótimas perguntas para entrevista. Uso prático limitado. Desejo C não têm os ponteiros :)
Himanshu
5
@Himanshu Se isso atrapalha o macarrão do entrevistado, tente o seguinte: tenha um ponteiro globalchar* p , apontando para uma sequência terminada válida de caracteres exclusivos. Então, uma função fn(char ch)que imprime tanto o chparâmetro e o caractere atual apontado pelo p. Agora, invoque fn(*p++);Q: fnimprime o mesmo caractere duas vezes ? Você ficaria surpreso com quantos professores erraram essa pergunta.
precisa saber é o seguinte
1
Como p aponta para uma string literal você deve escreverconst char* p = "Hello";
hetepeperfan

Respostas:

275

Aqui está uma explicação detalhada que, espero, será útil. Vamos começar com o seu programa, pois é o mais simples de explicar.

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

A primeira afirmação:

const char* p = "Hello";

declara pcomo um ponteiro para char. Quando dizemos "ponteiro para a char", o que isso significa? Isso significa que o valor de pé o endereço de a char; pnos diz onde na memória há algum espaço reservado para armazenar a char.

A instrução também inicializa ppara apontar para o primeiro caractere na cadeia literal "Hello". Para o exercício deste exercício, é importante entender pcomo apontar não para toda a cadeia, mas apenas para o primeiro caractere 'H'. Afinal, pé um ponteiro para um char, não para toda a string. O valor de pé o endereço do 'H'in "Hello".

Então você configura um loop:

while (*p++)

O que significa a condição do loop *p++? Aqui estão três coisas que tornam isso intrigante (pelo menos até que a familiaridade se manifeste):

  1. A precedência dos dois operadores, postfix ++e indirection*
  2. O valor de uma expressão de incremento postfix
  3. O efeito colateral de uma expressão de incremento postfix

1. Precedência . Uma rápida olhada na tabela de precedência para os operadores informará que o incremento do postfix tem uma precedência mais alta (16) do que a desreferência / indireção (15). Isto significa que a expressão complexa *p++vai ser agrupados como: *(p++). Ou seja, a *peça será aplicada ao valor da p++peça. Então, vamos p++participar primeiro.

2. Valor da expressão Postfix . O valor de p++é o valor de p antes do incremento . Se você tem:

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

a saída será:

7
8

porque i++avalia iantes do incremento. Da mesma forma, p++vai avaliar o valor atual de p. Como sabemos, o valor atual de pé o endereço de 'H'.

Então agora a p++parte de *p++foi avaliada; é o valor atual de p. Então a *parte acontece. *(current value of p)significa: acessar o valor no endereço mantido por p. Sabemos que o valor nesse endereço é 'H'. Portanto, a expressão é *p++avaliada como 'H'.

Agora espere um minuto, você está dizendo. Se for *p++avaliado 'H', por que isso não é 'H'impresso no código acima? É aí que entram os efeitos colaterais .

3. Efeitos colaterais da expressão do Postfix . O postfix ++tem o valor do operando atual, mas tem o efeito colateral de incrementar esse operando. Hã? Dê uma olhada nesse intcódigo novamente:

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

Como observado anteriormente, a saída será:

7
8

Quando i++é avaliado no primeiro printf(), ele avalia como 7. Mas o padrão C garante que, em algum momento antes do printf()início da execução do segundo , o efeito colateral do ++operador tenha ocorrido. Ou seja, antes que o segundo printf()aconteça, iserá incrementado como resultado do ++operador no primeiro printf(). A propósito, essa é uma das poucas garantias que o padrão oferece sobre o momento dos efeitos colaterais.

No seu código, então, quando a expressão *p++é avaliada, ela é avaliada como 'H'. Mas quando você chegar a isso:

printf ("%c", *p)

esse efeito colateral irritante ocorreu. pfoi incrementado. Uau! Não aponta mais para 'H', mas para o passado de um personagem 'H': para o 'e', em outras palavras. Isso explica sua saída do cockneyfied:

ello

Daí o coro de sugestões úteis (e precisas) nas outras respostas: para imprimir a pronúncia recebida "Hello"e não sua contraparte cockney, você precisa de algo como

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

Tanto para esse. E o resto? Você pergunta sobre o significado deles:

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

Acabamos de falar sobre o primeiro, então vamos olhar para o segundo: *++ptr.

Vimos em nossa explicação anterior que o incremento do postfix p++tem uma certa precedência , um valor e um efeito colateral . O incremento do prefixo ++ptem o mesmo efeito colateral da contraparte do postfix: incrementa seu operando em 1. No entanto, possui uma precedência diferente e um valor diferente .

O incremento do prefixo tem precedência menor que o postfix; ele tem precedência 15. Em outras palavras, ele tem a mesma precedência que o operador de desreferência / indireção *. Em uma expressão como

*++ptr

o que importa não é precedência: os dois operadores são idênticos em precedência. Assim, a associatividade entra em ação. O incremento do prefixo e o operador indireto têm associatividade direita-esquerda. Por causa dessa associatividade, o operando ptrserá agrupado com o operador mais à direita ++antes do operador mais à esquerda *. Em outras palavras, a expressão será agrupada *(++ptr). Portanto, como *ptr++por um motivo diferente, aqui também a *peça será aplicada ao valor da ++ptrpeça.

Então, qual é esse valor? O valor da expressão de incremento do prefixo é o valor do operando após o incremento . Isso o torna um animal muito diferente do operador de incremento postfix. Digamos que você tenha:

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

A saída será:

8
8

... diferente do que vimos com o operador postfix. Da mesma forma, se você tiver:

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

a saída será:

H e e l                // good dog

Você vê o porquê?

Agora chegamos à terceira expressão que você perguntou ++*ptr,. Esse é o mais difícil de todos, na verdade. Ambos os operadores têm a mesma precedência e associatividade direita-esquerda. Isso significa que a expressão será agrupada ++(*ptr). A ++peça será aplicada ao valor da *ptrpeça.

Então, se tivermos:

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

o resultado surpreendentemente egoísta será:

I

O que?! Ok, então a *pparte vai avaliar 'H'. Então o ++entra em jogo; nesse ponto, ele será aplicado ao 'H', e não ao ponteiro! O que acontece quando você adiciona 1 a 'H'? Você recebe 1 mais o valor ASCII de 'H'72; você começa 73. declara que como char, e você começa a charcom o valor ASCII de 73: 'I'.

Isso cuida das três expressões que você perguntou na sua pergunta. Aqui está outro, mencionado no primeiro comentário à sua pergunta:

(*ptr)++ 

Esse também é interessante. Se você tem:

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

isso lhe dará uma saída entusiasmada:

HI

O que está acontecendo? Novamente, é uma questão de precedência , valor da expressão e efeitos colaterais . Por causa dos parênteses, a *pparte é tratada como uma expressão primária. Expressões primárias superam todo o resto; eles são avaliados primeiro. E *p, como você sabe, avalia como 'H'. O restante da expressão, a ++parte, é aplicada a esse valor. Então, neste caso, (*p)++torna-se 'H'++.

Qual é o valor de 'H'++? Se você disse 'I'que esqueceu (já!) Nossa discussão sobre valor versus efeito colateral com incremento do postfix. Lembre-se, 'H'++avalia o valor atual de 'H' . Então, o primeiro printf()será impresso 'H'. Então, como efeito colateral , isso 'H'será incrementado para 'I'. O segundo printf()imprime isso 'I'. E você tem sua alegre saudação.

Tudo bem, mas nesses dois últimos casos, por que eu preciso

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

Por que não posso simplesmente ter algo como

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

Porque "Hello"é uma string literal. Se você tentar ++*p, você está tentando alterar 'H'a string para 'I', tornando a string inteira "Iello". Em C, os literais de seqüência de caracteres são somente leitura; tentar modificá-los invoca um comportamento indefinido. "Iello"também não está definido em inglês, mas isso é apenas coincidência.

Por outro lado, você não pode ter

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

Por que não? Porque, neste caso, pé uma matriz. Uma matriz não é um valor l modificável; você não pode alterar onde os ppontos são pré ou pós-incremento ou decremento, porque o nome da matriz funciona como se fosse um ponteiro constante. (Isso não é o que realmente é; é apenas uma maneira conveniente de ver isso.)

Para resumir, aqui estão as três coisas que você perguntou:

*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

E aqui está um quarto, tão divertido quanto os outros três:

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

O primeiro e o segundo travarão se, ptrna verdade, for um identificador de matriz. O terceiro e o quarto travam se ptrapontarem para uma string literal.

Aí está. Espero que esteja tudo cristal agora. Você tem sido um ótimo público, e eu estarei aqui a semana toda.

verboso
fonte
22
Antes de entrar neste fórum, pesquisei 3 livros "C" que possuo. Eu também tentei alguns tutoriais on-line notáveis. Mas nenhum deles chega perto da sua explicação (especialmente a maneira como você reuniu tudo). Você não apenas respondeu à pergunta que fiz, mas também discutiu muito mais coisas do nível de base. Na verdade, você me ensinou muitas coisas básicas hoje, das quais me faltava antes. Não pude deixar de alternar minha resposta aceita. :) Obrigado novamente.
alocado
26
+1 Acho que esta é a melhor resposta longa que li no SO. Acho que todo mundo poderia aprender muito com essa resposta.
Shafik Yaghmour
9
Você, senhor, deve escrever um livro sobre C.
Dillon Burton
1
Que bela resposta para uma boa pergunta! Bem feito @verbose!
Benka
7
@verbose o senhor, ter vivido até seu nome .. :)
sleeping_dragon
44

Suponha ptrpontos para o i-ésimo elemento da matriz arr.

  1. *ptr++avalia arr[i]e define ptrpara apontar para o (i + 1) -ésimo elemento de arr. É equivalente a *(ptr++).

  2. *++ptrdefine ptrpara apontar para o (i + 1) -ésimo elemento de arre avalia como arr[i+1]. É equivalente a *(++ptr).

  3. ++*ptraumenta arr[i]em um e avalia seu valor aumentado; o ponteiro ptré deixado intocado. É equivalente a ++(*ptr).

Também há mais um, mas você precisará de parênteses para escrevê-lo:

  1. (*ptr)++aumenta arr[i]em um e avalia seu valor antes de ser aumentado; o ponteiro ptré novamente deixado intocado.

O resto você pode descobrir por si mesmo; Também foi respondido por @Jaguar.

nickie
fonte
13

*ptr++ : post increment a pointer ptr

*++ptr : Pre Increment a pointer ptr

++*ptr : preincrement the value at ptr location

Leia aqui sobre operadores de pré-incremento e pós-incremento


Isso dará Hellocomo saída

int main()
{
    const char *p = "Hello";
    while(*p)
         printf("%c",*p++);//Increment the pointer here 
    return 0;
}
Jainendra
fonte
@ Nik-Lz Sim, a saída seriaHello
Jainendra 10/10
7

A condição no seu loop é ruim:

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

É o mesmo que

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

E isso está errado, deve ser:

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

*ptr++é o mesmo que *(ptr++), que é:

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

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

*++ptré o mesmo que *(++ptr), que é:

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

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

++*ptré o mesmo que ++(*ptr), que é:

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

value = *ptr;
++value;
printf("%c", value); // will print 'f' ('e' + 1)
nouney
fonte
Concordo absolutamente com a primeira parte da resposta. Na segunda parte, inicializar ponteiros (para números inteiros!) Com números inteiros é confuso para alguém que está lutando para entender o uso do ponteiro.
nickie
4

Você está certo quanto à precedência, observe que ele *tem precedência sobre o incremento do prefixo, mas não sobre o incremento do postfix. Veja como essas desagregações:

*ptr++ - indo da esquerda para a direita, desreferencia o ponteiro e, em seguida, aumente o valor do ponteiro (não o que ele aponta, devido à precedência do postfix sobre a desreferência)

*++ptr - incrementar o ponteiro e depois desreferenciá-lo, isso ocorre porque o prefixo e o desreferência têm a mesma precedência e, portanto, são avaliados na ordem da direita para a esquerda

++*ptr- semelhante ao anterior em termos de precedência, passando novamente da direita para a esquerda para desreferenciar o ponteiro e depois incrementar o que o ponteiro aponta. Observe que, no seu caso, esse erro levará a um comportamento indefinido, porque você está tentando modificar uma variável somente leitura ( char* p = "Hello";).

Nobilis
fonte
3

Vou adicionar minha opinião, porque enquanto as outras respostas estão corretas, acho que estão faltando alguma coisa.

 v = *ptr++

significa

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

Enquanto que

 v = *++ptr

significa

 ptr = ptr + 1
 v   = *ptr

É importante entender que pós incremento (e pós decremento) significa

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

Por que isso Importa? Bem, em C isso não é tão importante. Em C ++, porém, ptrpode ser um tipo complexo, como um iterador. Por exemplo

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

Nesse caso, por itser um tipo complexo, it++pode ter efeitos colaterais por causa da tempcriação. Obviamente, se você tiver sorte, o compilador tentará jogar fora o código que não é necessário, mas se o construtor ou o destruidor do iterador fizer alguma coisa, ele it++mostrará esses efeitos quando ele criar temp.

O resumo do que estou tentando dizer é Escreva o que você quer dizer . Se você quer dizer increment ptr, então ++ptrnão escreva ptr++. Se você quer dizer temp = ptr, ptr += 1, temp, escrevaptr++

gman
fonte
0
*ptr++    // 1

É o mesmo que:

    tmp = *ptr;
    ptr++;

Portanto, o valor do objeto apontado por ptré recuperado e, em seguida, ptrincrementado.

*++ptr    // 2

É o mesmo que:

    ++ptr;
    tmp = *ptr;

Portanto, o ponteiro ptré incrementado e o objeto apontado por ptré lido.

++*ptr    // 3

É o mesmo que:

    ++(*ptr);

Portanto, o objeto apontado por ptré incrementado; ptrem si é inalterado.

David R Tribble
fonte
0

O postfix e o prefixo têm maior precedência do que a desreferência, portanto

* ptr ++ aqui pós incremento ptr e, em seguida, aponta para o novo valor de ptr

* ++ ptr aqui Pre Incrementar o punho, apontando para o novo valor de ptr

++ * ptr aqui primeiro obtém o valor de ptr apontando e incrementando esse vlaue

Kiran Padwal
fonte
1
Isto está incorreto. O Postfix tem precedência mais alta, mas o prefixo tem a mesma precedência que a dereferência.
verboso
0

Expressões de ponteiro: * ptr ++, * ++ ptr e ++ * ptr:

Nota : os ponteiros devem ser inicializados e devem ter um endereço válido. Como na RAM, além do nosso programa (a.out), há muito mais programas em execução simultaneamente, ou seja, se você tentar acessar alguma memória que não foi reservada para o seu sistema operacional, ocorrerá uma falha de segmentação.

Antes de explicar isso, vamos considerar um exemplo simples?

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

analisar a saída do código acima, espero que você tenha obtido a saída do código acima. Uma coisa é clara a partir do código acima: o nome do ponteiro ( ptr ) significa que estamos falando de endereço e * ptr significa que estamos falando de valores / dados.

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

acima mencionadas, todas as quatro sintaxes são semelhantes, address gets incrementedmas todas, como o endereço é incrementado, isso é diferente.

Nota : para resolver qualquer expressão, descubra quantos operadores existem na expressão e descubra as prioridades do operador. Múltiplos operadores com a mesma prioridade e verifico a ordem da evolução ou associatividade que pode da direita (R) para a esquerda (L) ou da esquerda para a direita.

* ptr ++ : Aqui existem 2 operadores, nomeadamente des-referência (*) e ++ (incremento). Ambos têm a mesma prioridade e depois checam a associatividade que é de R a L. Portanto, começa a resolver da direita para a esquerda, quaisquer que sejam os operadores que estão chegando primeiro.

* ptr ++ : first ++ surgiu durante a resolução de R para L, de modo que o endereço é incrementado, mas seu pós-incremento.

* ++ ptr : O mesmo que o primeiro endereço aqui também é incrementado, mas seu pré-incremento.

* (ptr ++) : Aqui existem 3 operadores, entre os quais o agrupamento () com prioridade mais alta, então primeiro o ptr ++ resolvido, ou seja, o endereço é incrementado, mas é postado.

* (++ ptr) : O mesmo que o caso acima aqui também é incrementado, mas o pré-incremento.

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

acima mencionado, todas as quatro sintaxes são semelhantes, em todos os valores / dados é incrementado, mas como o valor é alterado é diferente.

++ * ptr : first * veio durante a resolução de R para L, então o valor é alterado, mas seu pré-incremento.

++ (* ptr) : igual ao caso acima, o valor é modificado.

(* ptr) ++ : Aqui existem 3 operadores, dentre os quais o agrupamento () com prioridade mais alta, Inside () * ptr existe, então primeiro * ptr é resolvido, ou seja, o valor é incrementado, mas é postado.

Nota : ++ * ptr e * ptr = * ptr + 1 são iguais, em ambos os casos o valor é alterado. ++ * ptr: apenas 1 instrução (INC) é usada, o valor diretamente é alterado em um único disparo. * ptr = * ptr + 1: aqui o primeiro valor é incrementado (INC) e depois atribuído (MOV).

Para entender todas as diferentes sintaxes de incremento acima no ponteiro, vamos considerar um código simples:

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

No código acima, tente comentar / descomentar comentários e analisar as saídas.

Ponteiros como constantes : não existem maneiras pelas quais você pode tornar os ponteiros tão constantes, poucos que estou mencionando aqui.

1) const int * p OU int const * p : Aqui valueé constante , o endereço não é constante, ou seja, onde p está apontando? Algum endereço? Nesse endereço, qual é o valor? Algum valor certo? Esse valor é constante, você não pode modificar esse valor, mas para onde o ponteiro está apontando? Algum endereço certo? Também pode apontar para outro endereço.

Para entender isso, vamos considerar o código abaixo:

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

Tente analisar a saída do código acima

2) int const * p : é chamado ' **constant pointe**r' ie address is constant but value is not constant. Aqui você não tem permissão para alterar o endereço, mas pode modificar o valor.

Nota : o ponteiro constante (acima do caso) deve ser inicializado enquanto se declara.

Para entender isso, verifique o código simples.

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

No código acima, se você observar que não há ++ * p ou * p ++, você pode pensar que este é um caso simples, porque não estamos mudando endereço ou valor, mas isso produzirá erro. Por quê ? Razão que menciono nos comentários.

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

Então, qual é a solução desse problema?

     int* const p = &x;

para mais informações sobre este caso, vamos considerar o exemplo abaixo.

#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 : Aqui, endereço e valor são constantes .

Para entender isso, verifique o código abaixo

#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);
}
Achal
fonte
-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 que você está tentando incrementar o valor ASCII do *pqual

   is "Hello"
       ^
       | 
       p

você não pode incrementar o valor porque é uma constante, para que você receba um erro

quanto ao loop while, o loop é executado até *p++atingir o final da string em que existe um '\0'caractere (NULL).

Agora, desde que *p++pule o primeiro caractere, você apenas obterá sua saída a partir do segundo caractere.

O código a seguir não produzirá nada porque o loop while foi '\0'

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

O código a seguir fornecerá a mesma saída que o próximo código, ou seja, ello.

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

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

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