Expresiones de puntero: * ptr ++, * ++ ptr y ++ * ptr


128

Recientemente me he encontrado con este problema que no puedo entender por mí mismo.

¿Qué significan realmente estas tres expresiones ?

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

He intentado con Ritchie. Pero desafortunadamente no pudo seguir lo que dijo sobre estas 3 operaciones.

Sé que todos se realizan para incrementar el puntero / el valor señalado. También puedo suponer que puede haber muchas cosas sobre la precedencia y el orden de evaluación. Al igual que uno incrementa el puntero primero, luego obtiene el contenido de ese puntero, uno simplemente recupera el contenido y luego incrementa el puntero, etc. etc. Como puede ver, no tengo una comprensión clara sobre sus operaciones reales , lo que me gustaría despejar lo antes posible. Pero estoy realmente perdido cuando tengo la oportunidad de aplicarlos en los programas. Por ejemplo:

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

me da esta salida:

ello

Pero mi expectativa era que se imprimiría Hello. Una solicitud final: déme ejemplos de cómo funciona cada expresión en un fragmento de código dado. Como la mayoría de las veces, solo un simple párrafo de teoría se me pasa por la cabeza.


66
Te perdiste el cuarto: (*ptr)++(paréntesis necesarios para desambiguar *ptr++)
user4815162342

15
Porque incrementó el puntero antes de imprimirlo. Querías while (* p) e printf ("% c", * p ++);
dcaswell

Grandes preguntas para la entrevista. Uso práctico limitado. Desearía que C no tuviera esos punteros :)
Himanshu

55
@Himanshu Si eso hornea los fideos de su entrevistado, intente esto: tenga un puntero globalchar* p , señalando una cadena terminada válida de caracteres únicos. Luego tenga una función fn(char ch)que imprima tanto el chparámetro como el carácter actual señalado por p. Ahora invoque fn(*p++);P: ¿ fnImprime el mismo personaje dos veces ? Te sorprendería cuántos profesores se equivocan con esa pregunta.
WhozCraig

1
dado que p apunta a un literal de cadena que debe escribirconst char* p = "Hello";
hetepeperfan

Respuestas:


275

Aquí hay una explicación detallada que espero sea útil. Comencemos con su programa, ya que es el más simple de explicar.

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

La primera declaración:

const char* p = "Hello";

declara pcomo puntero a char. Cuando decimos "puntero a un char", ¿qué significa eso? Significa que el valor de pes la dirección de a char; pnos dice dónde en la memoria hay un espacio reservado para guardar a char.

La instrucción también se inicializa ppara señalar el primer carácter en el literal de cadena "Hello". Por el bien de este ejercicio, es importante entender pque no apunta a toda la cadena, sino solo al primer carácter 'H',. Después de todo, pes un puntero a uno char, no a toda la cadena. El valor de pes la dirección de la 'H'en "Hello".

Luego configuras un bucle:

while (*p++)

¿Qué significa la condición de bucle *p++? Aquí hay tres cosas que hacen que esto sea desconcertante (al menos hasta que se establezca la familiaridad):

  1. La precedencia de los dos operadores, postfix ++e indirection*
  2. El valor de una expresión de incremento de postfix
  3. El efecto secundario de una expresión de incremento de postfix

1. Precedencia . Un rápido vistazo a la tabla de precedencia para operadores le dirá que el incremento de postfix tiene una precedencia más alta (16) que la desreferencia / indirección (15). Esto significa que el complejo de expresión *p++va a ser agrupados como: *(p++). Es decir, la *parte se aplicará al valor de la p++parte. Así que tomemos la p++parte primero.

2. Valor de expresión de postfix . El valor de p++es el valor de p antes del incremento . Si usted tiene:

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

la salida será:

7
8

porque i++evalúa iantes del incremento. Del mismo modo p++se va a evaluar el valor actual de p. Como sabemos, el valor actual de pes la dirección de 'H'.

Entonces ahora la p++parte de *p++ha sido evaluada; que es el valor actual de p. Entonces *sucede la parte. *(current value of p)significa: acceder al valor en la dirección que posee p. Sabemos que el valor en esa dirección es 'H'. Entonces la expresión se *p++evalúa como 'H'.

Ahora espera un minuto, estás diciendo. Si se *p++evalúa como 'H', ¿por qué eso no se 'H'imprime en el código anterior? Ahí es donde entran los efectos secundarios .

3. Postfix expresión efectos secundarios . El postfix ++tiene el valor del operando actual, pero tiene el efecto secundario de incrementar ese operando. ¿Eh? Eche un vistazo a ese intcódigo nuevamente:

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

Como se señaló anteriormente, el resultado será:

7
8

Cuando i++se evalúa en el primero printf(), se evalúa a 7. Pero el estándar C garantiza que en algún momento antes de que el segundo printf()comience a ejecutarse, el efecto secundario del ++operador habrá tenido lugar. Es decir, antes de que printf()ocurra lo segundo , ise habrá incrementado como resultado del ++operador en lo primero printf(). Esto, por cierto, es una de las pocas garantías que ofrece el estándar sobre el momento de los efectos secundarios.

En su código, entonces, cuando *p++se evalúa la expresión , se evalúa como 'H'. Pero para cuando llegues a esto:

printf ("%c", *p)

ese molesto efecto secundario ha ocurrido. pha sido incrementado Whoa! Ya no apunta a 'H', sino a un pasado del personaje 'H': al 'e', en otras palabras. Eso explica su salida cockneyfied:

ello

De ahí el coro de sugerencias útiles (y precisas) en las otras respuestas: para imprimir la pronunciación recibida "Hello"y no su contraparte cockney, necesita algo como

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

Mucho para eso. ¿Qué pasa con el resto? Usted pregunta sobre el significado de estos:

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

Acabamos de hablar sobre la primera, por lo que vamos a ver el segundo: *++ptr.

Vimos en nuestra explicación anterior que el incremento de postfix p++tiene cierta precedencia , un valor y un efecto secundario . El incremento de prefijo ++ptiene el mismo efecto secundario que su contraparte postfix: incrementa su operando en 1. Sin embargo, tiene una precedencia diferente y un valor diferente .

El incremento de prefijo tiene una precedencia menor que el postfix; tiene prioridad 15. En otras palabras, tiene la misma prioridad que el operador de desreferencia / indirección *. En una expresión como

*++ptr

lo importante no es la precedencia: los dos operadores son idénticos en precedencia. Entonces la asociatividad entra en acción. El incremento de prefijo y el operador de indirección tienen asociatividad derecha-izquierda. Debido a esa asociatividad, el operando ptrse agrupará con el operador más a la derecha ++antes que el operador más a la izquierda *,. En otras palabras, la expresión se va a agrupar *(++ptr). Entonces, como con *ptr++pero por una razón diferente, aquí también la *parte se aplicará al valor de la ++ptrparte.

Entonces, ¿cuál es ese valor? El valor de la expresión de incremento de prefijo es el valor del operando después del incremento . Esto lo convierte en una bestia muy diferente del operador de incremento de postfix. Digamos que tienes:

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

El resultado será:

8
8

... diferente de lo que vimos con el operador postfix. Del mismo modo, si tiene:

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

la salida será:

H e e l                // good dog

¿Ves por qué?

Ahora llegamos a la tercera expresión que preguntaste, ++*ptr. Ese es el más complicado de todos, en realidad. Ambos operadores tienen la misma precedencia y asociatividad derecha-izquierda. Esto significa que la expresión se agrupará ++(*ptr). La ++parte se aplicará al valor de la *ptrparte.

Entonces si tenemos:

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

El resultado sorprendentemente egoísta será:

I

¡¿Qué?! Bien, entonces la *pparte se va a evaluar 'H'. Luego ++entra en juego, en ese momento, se aplicará al 'H'puntero, ¡no al puntero en absoluto! ¿Qué sucede cuando agregas 1 a 'H'? Obtiene 1 más el valor ASCII de 'H'72; se obtiene 73. Representar que como char, y se obtiene el charcon el valor ASCII de 73: 'I'.

Eso se encarga de las tres expresiones que preguntaste en tu pregunta. Aquí hay otro, mencionado en el primer comentario a su pregunta:

(*ptr)++ 

Ese también es interesante. Si usted tiene:

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

te dará esta salida entusiasta:

HI

¿Que esta pasando? Nuevamente, es una cuestión de precedencia , valor de expresión y efectos secundarios . Debido a los paréntesis, la *pparte se trata como una expresión primaria. Las expresiones primarias triunfan sobre todo lo demás; son evaluados primero. Y *p, como sabes, evalúa a 'H'. El resto de la expresión, la ++parte, se aplica a ese valor. Entonces, en este caso, se (*p)++convierte 'H'++.

¿Cuál es el valor de 'H'++? Si dijiste 'I', has olvidado (¡ya!) Nuestra discusión sobre el valor frente a los efectos secundarios con el incremento de postfix. Recuerde, 'H'++evalúa el valor actual de 'H' . Entonces eso primero printf()se va a imprimir 'H'. Luego, como efecto secundario , 'H'se incrementará a 'I'. El segundo printf()imprime eso 'I'. Y tienes tu alegre saludo.

De acuerdo, pero en esos dos últimos casos, ¿por qué necesito

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

¿Por qué no puedo tener algo como

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

Porque "Hello"es una cadena literal. Si lo intentas ++*p, estás tratando de cambiar 'H'la cadena a 'I', haciendo que toda la cadena "Iello". En C, los literales de cadena son de solo lectura; intentar modificarlos invoca un comportamiento indefinido. "Iello"no está definido en inglés también, pero eso es solo una coincidencia.

Por el contrario, no puedes tener

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

Por qué no? Porque en este caso, pes una matriz. Una matriz no es un valor l modificable; no puede cambiar los ppuntos por incremento o decremento previo o posterior, porque el nombre de la matriz funciona como si fuera un puntero constante. (Eso no es lo que realmente es; esa es solo una forma conveniente de verlo).

En resumen, estas son las tres cosas que preguntaste:

*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

Y aquí hay un cuarto, tan divertido como los otros tres:

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

El primero y el segundo se bloquearán si en ptrrealidad es un identificador de matriz. El tercero y el cuarto se bloquearán si ptrapunta a una cadena literal.

Ahí tienes. Espero que todo sea cristal ahora. Has sido una gran audiencia, y estaré aquí toda la semana.


22
Antes de venir a este foro, he buscado 3 libros "C" que poseo. También probé algunos tutoriales en línea notables. Pero ninguno de ellos se acerca a su explicación (especialmente la forma en que lo ha preparado todo). No solo ha respondido la pregunta que le he hecho, sino que también ha discutido muchas más cosas desde el nivel de base. En realidad, hoy me has enseñado muchas cosas básicas, que antes me faltaban. No pude evitar alternar mi respuesta aceptada. :) Gracias de nuevo.
asignado el

26
+1 Creo que esta es la mejor respuesta larga que he leído en SO. Creo que todos podrían aprender mucho de esta respuesta.
Shafik Yaghmour

9
Señor, debería escribir un libro sobre C.
Dillon Burton

1
¡Qué hermosa respuesta a una buena pregunta! ¡Bien hecho @verbose!
benka

77
@verbose, señor, ha estado a la altura de su nombre .. :)
sleeping_dragon

44

Supongamos que ptrapunta al elemento i-ésimo de la matriz arr.

  1. *ptr++evalúa arr[i]y establece ptrpara señalar el elemento (i + 1) -th de arr. Es equivalente a *(ptr++).

  2. *++ptrestablece ptrque apunta al elemento (i + 1) -th de arry evalúa a arr[i+1]. Es equivalente a *(++ptr).

  3. ++*ptraumenta arr[i]en uno y evalúa su valor aumentado; el puntero ptrse deja intacto. Es equivalente a ++(*ptr).

También hay uno más, pero necesitarías paréntesis para escribirlo:

  1. (*ptr)++aumenta arr[i]en uno y evalúa su valor antes de ser aumentado; el puntero ptrse deja nuevamente intacto.

El resto lo puedes resolver tú mismo; También fue respondido por @Jaguar.


13

*ptr++ : post increment a pointer ptr

*++ptr : Pre Increment a pointer ptr

++*ptr : preincrement the value at ptr location

Lea aquí sobre los operadores de incremento previo y posterior.


Esto dará Hellocomo salida

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

@ Nik-Lz Sí, la salida seríaHello
Jainendra

7

La condición en tu circuito es mala:

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

Es lo mismo que

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

Y eso está mal, esto debería ser:

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

*ptr++es lo mismo que *(ptr++), que es:

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

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

*++ptres lo mismo que *(++ptr), que es:

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

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

++*ptres lo mismo que ++(*ptr), que es:

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

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

Estoy totalmente de acuerdo con la primera parte de la respuesta. En la segunda parte, inicializar punteros (¡a enteros!) Con enteros es confuso para alguien que está luchando por comprender el uso del puntero.
nickie

4

Tiene razón sobre la precedencia, tenga en cuenta que *tiene precedencia sobre el incremento de prefijo, pero no sobre el incremento de postfix. Así es como se desglosan:

*ptr++ - ir de izquierda a derecha, desreferenciar el puntero y luego incrementar el valor del puntero (no a lo que apunta, debido a la precedencia de postfix sobre la desreferencia)

*++ptr - incremente el puntero y luego desreferenciarlo, esto se debe a que el prefijo y la desreferencia tienen la misma precedencia, por lo que se evalúan en orden de derecha a izquierda

++*ptr- similar a lo anterior en términos de precedencia, nuevamente yendo de derecha a izquierda para desreferenciar el puntero y luego incrementar lo que apunta el puntero. Tenga en cuenta que en su caso, este conducirá a un comportamiento indefinido porque está intentando modificar una variable de solo lectura ( char* p = "Hello";).


3

Voy a agregar mi opinión porque si bien las otras respuestas son correctas, creo que les falta algo.

 v = *ptr++

medio

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

Donde como

 v = *++ptr

medio

 ptr = ptr + 1
 v   = *ptr

Es importante entender que el incremento posterior (y el decremento posterior) significan

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

¿Por qué eso importa? Bueno, en C eso no es tan importante. Sin embargo, en C ++ ptrpodría ser un tipo complejo como un iterador. Por ejemplo

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

En este caso, porque ites un tipo complejo it++puede tener efectos secundarios debido a la tempcreación. Por supuesto, si tiene suerte, el compilador intentará desechar el código que no es necesario, pero si el constructor o destructor del iterador hace algo, it++mostrará esos efectos cuando creetemp .

Lo corto de lo que intento decir es Escribe lo que quieres decir . Si quiere decir increment ptr, entonces ++ptrno escriba ptr++. Si te refieres, temp = ptr, ptr += 1, tempentonces escribeptr++


0
*ptr++    // 1

Esto es lo mismo que:

    tmp = *ptr;
    ptr++;

Entonces ptrse recupera el valor del objeto señalado por , luego ptrse incrementa.

*++ptr    // 2

Esto es lo mismo que:

    ++ptr;
    tmp = *ptr;

Entonces, el puntero ptrse incrementa, luego ptrse lee el objeto señalado por .

++*ptr    // 3

Esto es lo mismo que:

    ++(*ptr);

Entonces el objeto señalado por ptrse incrementa; ptren sí no ha cambiado.


0

postfix y prefix tienen mayor prioridad que la desreferencia

* ptr ++ aquí publica increment ptr y luego apunta al nuevo valor de ptr

* ++ ptr aquí Pre Increment puño luego apuntando a un nuevo valor de ptr

++ * ptr aquí primero obtiene el valor de ptr apuntando e incrementa esa vlaue


1
Esto es incorrecto. Postfix tiene mayor prioridad, pero el prefijo tiene la misma prioridad que la desreferencia.
detallado

0

Expresiones de puntero: * ptr ++, * ++ ptr y ++ * ptr:

Nota : los punteros deben inicializarse y deben tener una dirección válida. Porque en la RAM, aparte de nuestro programa (a.out), hay muchos más programas ejecutándose simultáneamente, es decir, si intenta acceder a alguna memoria que no estaba reservada para su sistema operativo, se producirá un error de segmentación.

Antes de explicar esto, consideremos un ejemplo simple.

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

analice la salida del código anterior, espero que haya obtenido la salida del código anterior. Una cosa está clara en el código anterior es que el nombre del puntero ( ptr ) significa que estamos hablando de dirección y * ptr significa que estamos hablando de valor / datos.

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

Las 4 sintaxis mencionadas anteriormente son similares, address gets incrementedpero la forma en que se incrementa la dirección es diferente.

Nota : para resolver cualquier expresión, averigüe cuántos operadores hay en la expresión, luego descubra las prioridades del operador. Si varios operadores tienen la misma prioridad, compruebo el orden de evolución o asociatividad que puede ser de derecha (R) a izquierda (L) o de izquierda a derecha.

* ptr ++ : Aquí hay 2 operadores, a saber, desreferenciación (*) e ++ (incremento). Ambos tienen la misma prioridad, luego verifique la asociatividad que es de R a L. Así que comienza a resolver de derecha a izquierda, cualesquiera operadores que vengan primero.

* ptr ++ : first ++ llegó al resolver de R a L, por lo que la dirección se incrementa pero su incremento posterior.

* ++ ptr : Igual que el primero aquí, la dirección también se incrementa pero su incremento previo.

* (ptr ++) : Aquí hay 3 operadores, entre ellos el agrupamiento () que tiene la más alta prioridad, así que primero se resuelve ptr ++, es decir, la dirección se incrementa pero se publica.

* (++ ptr) : Igual que el caso anterior, aquí también la dirección se incrementa pero se incrementa previamente.

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

Las 4 sintaxis anteriores son similares, en todos los valores / datos se incrementan, pero la forma en que se cambia el valor es diferente.

++ * ptr : first * llegó al resolver de R a L, por lo que el valor se cambia pero su incremento previo.

++ (* ptr) : Igual que el caso anterior, el valor se modifica.

(* ptr) ++ : Aquí hay 3 operadores, entre ellos el agrupamiento () que tiene la máxima prioridad, Inside () * ptr está allí, así que primero * ptr se resuelve, es decir, el valor se incrementa pero se publica.

Nota : ++ * ptr y * ptr = * ptr + 1 ambos son iguales, en ambos casos el valor cambia. ++ * ptr: solo se usa 1 instrucción (INC), el valor directamente se cambia en un solo disparo. * ptr = * ptr + 1: aquí el primer valor se incrementa (INC) y luego se asigna (MOV).

Para comprender todas las diferentes sintaxis de incremento anteriores en el puntero, consideremos un código simple:

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

En el código anterior, intente comentar / descomentar comentarios y analizar resultados.

Punteros como constantes : no hay maneras en que pueda hacer que los punteros sean constantes, pocos los menciono aquí.

1) const int * p OR int const * p : Aquí valuees constante , la dirección no es constante , es decir, ¿hacia dónde apunta p? Alguna dirección? En esa dirección, ¿cuál es el valor? Algún valor ¿verdad? Ese valor es constante, no puede modificar ese valor, pero ¿dónde apunta el puntero? Alguna direccion correcta? Puede apuntar a otra dirección también.

Para entender esto, consideremos el siguiente código:

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

Intenta analizar la salida del código anterior

2) int const * p : se llama ' **constant pointe**r' es decir address is constant but value is not constant. Aquí no puede cambiar la dirección, pero puede modificar el valor.

Nota : el puntero constante (caso anterior) debe inicializarse mientras se declara.

Para entender esto, verifiquemos el código simple.

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

En el código anterior, si observa que no hay ++ * p o * p ++ Entonces puede pensar que este es un caso simple porque no estamos cambiando la dirección o el valor, pero producirá un error. Por qué ? Razón que menciono en los comentarios.

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

Entonces, ¿cuál es la solución de este problema?

     int* const p = &x;

para obtener más información sobre este caso, consideremos el siguiente ejemplo.

#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 : Aquí tanto la dirección como el valor son constantes .

Para entender esto, verifiquemos el siguiente código

#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 que está intentando incrementar el valor ASCII del *pcual

   is "Hello"
       ^
       | 
       p

no puede incrementar el valor porque es una constante, por lo que obtendría un error

en cuanto a su ciclo while, el ciclo se ejecuta hasta *p++llegar al final de la cadena donde hay un'\0' (NULO).

Ahora desde *p++ omite el primer carácter, solo obtendrá su salida a partir del segundo carácter.

El siguiente código no generará nada porque mientras el bucle tiene '\0'

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

El siguiente código le dará la misma salida que el siguiente código, es decir, ello.

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

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

const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.