impresión de un puntero char … ¿qué sucede?

soy nuevo en C y tengo una pregunta acerca de punteros char y lo que se va a imprimir . echale un vistazo :

int main()
{
char *p1="ABCD";
p1="EFG";
printf ("%s",p1);
return 0;
}

se va a imprimir EFG

y ahora :

int main()
{
char *p1="ABCD";
//p1="EFG";
printf ("%s",p1);
return 0;
}

y le dará ABCD

El punto de que yo no entiendo es lo que exactamente *p1 es ?

Es un número de una dirección que contiene un char valor ?
Es un char ?

lo que está en *p1 ahora ? ¿Por qué es const ?

  • p1 es un puntero al primer carácter en una cadena. Eso es todo.
  • es char, y const aún no define a ser así, y el primer carácter de la cadena que dar.
  • Abundando en lo @OliverCharlesworth dijo: Cuando C fue de nuevo, la gente de aprendizaje que se utiliza para el lenguaje Ensamblador y comprendió intuitivamente que un puntero era sólo una variable que contiene la dirección de algo. En una palabra máquina, char* podría ser la dirección de una palabra y un carácter de desplazamiento. Pero la noción puntero ha evolucionado a medida que las lenguas evolucionan. En C++, los punteros se han generalizado a los iteradores, que pueden ser ellos mismos los objetos complejos. No es útil pensar en términos de lo que es un puntero que realmente es, bajo el capó. Un puntero apunta a algo. No importa cómo.
  • eso no es cool. vivo en la C significa vivir con los punteros. es esencial saber qué es exactamente puntero es, sin ningún tipo de sesgo. no blackbox obras en la c.
InformationsquelleAutor Behrus58 | 2014-12-23

8 Kommentare

  1. 3

    De la C Estándar:

    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

    EXAMPLE 8 The declaration
    
      char s[] = "abc", t[3] = "abc";
      defines ‘‘plain’’ char array objects s and t whose elements are initialized with character string literals.
    
    This declaration is identical to
    
      char s[] = { 'a', 'b', 'c', '\0' },
      t[] = { 'a', 'b', 'c' };
    
    The contents of the arrays are modifiable. On the other hand, the declaration
    
      char *p = "abc";
    
    defines p with type ‘‘pointer to char’’ and initializes it to point to an object
    with type ‘‘array of char’’ with length 4 whose elements are initialized with a
    character string literal. If an attempt is made to use p to modify the contents
    of the array, the behavior is undefined.

    En otras palabras:

    1) char *p1; declara una variable (p1), que es un puntero. El puntero, p1 puede ser cambiado.

    2) char *p1 = "ABCD"; declara p1 (igual a «1») y también inicializa los datos que los puntos a (la inicializa con el de sólo lectura, 5-lelement matriz de caracteres «ABCD\0»).

    Así que usted puede cambiar la dirección de «p1» puntos a (usted puede hacer que el punto de «EFG», asignar NULL, etc. etc). Pero NO cambiar de manera segura los datos en sí. Usted probablemente obtendrá una «infracción de acceso» si intenta sobrescribir «ABCD». El comportamiento exacto es «undefined» – NADA puede suceder.

    3) char p2[] = "ABCD"; declara una variable (p2) que es una matriz. Se asigna 5 caracteres, e inicializa los datos a «ABCD\0».

    La matriz es de lectura-escritura (usted puede cambiar los datos en la matriz), pero la variable «p2» no se puede cambiar (no se puede cambiar p2 para que apunte a una dirección diferente, porque no es un puntero).

    4) ¿cuál es la «diferencia» entre un char *puntero y una matriz de char[]? Aquí hay una buena discusión:

    http://c-faq.com/aryptr/aryptrequiv.html

    • N1124 es un borrador del estándar C99. N1256 es una forma más actual de C99 proyecto; incluye los tres Rectificaciones Técnicas. N1570 es la última disponible públicamente proyecto de 2011 C ISO estándar.
    • El texto que he citado es exactamente el mismo en ambas versiones: me acaba de pasar para encontrar un enlace a la primer borrador. He actualizado la citación a N1256. Una lista de todo lo relacionado con C/ISO documentación está aquí: open-std.org/jtc1/sc22/wg14/www/projects#9899. Francamente, me gustaría recomendar sólo la lectura de K&R.
    • K&R es excelente para algunos propósitos, pero (a) no está pensada como una definición rigurosa de la lengua (la mayoría de ella es más de un tutorial), y (b) la segunda edición de «K&R2» se refiere a la versión de 1990 de la lengua. Ha habido dos actualizada de normas desde luego, en 1999 y 2011. Pero sí, K&R es casi seguro que mejor que el estándar ISO para aprender el idioma.
  2. 1

    p1 es un tipo de puntero que contiene la dirección de donde el compilador poner «ABCD» en la memoria. La dirección del primer carácter en la matriz.

    Cuando usted tiene char *p1 = "ABCD"; usted se acaba de asignar el valor de la dirección que se celebró en p1.
    Al reasignar p1 = "EFG"; vuelve a asignar el puntero a una nueva dirección (donde «EFG» es)

    printf ("%s",p1); imprime el contenido de la memoria en la ubicación p1 puntos.

  3. 1

    Inicialmente p1 es declarado como un puntero char y apunta a «ABCD» (dirección base de «ABCD»).

    Más tarde el puntero que señala a «EFG» (contiene la dirección base de «EFG»)

    +----+      +---+
    |ABCD|      |EFG|
    +----+      +---+
     1000        2000
    
    char *p1="ABCD";
             +----+
    before   |1000|
             +----+
              p1
    p1="EFG";
    After    +----+
             |2000|
             +----+
              p1
    • ¿No viceversa 😀 ?!
  4. 1

    p1 es un char puntero que contiene la dirección de la base de o dirección de inicio o la dirección del primer elemento de la cadena asignado mediante = operador.

    En su primer código, ha asignado la dirección de la base de la «ABCD», para que, más tarde, la dirección de la base de «EFG» [que sobrescribe el valor anterior], y por último de la impresión. Así, el valor más reciente [«EFG»] se imprime.

    En el segundo caso, se va a asignar la dirección de la base de la «ABCD», y de la impresión. Así se imprime ABCD.
    Tal vez vale la pena mencionar, el %s especificador de formato en printf() espera que la partida dirección de una cadena terminada en null, que está aquí, señalado por p1.

    Como por la const parte, el valor de la cadena señalado por p1 es constante en este caso, como literales de cadena son generalmente almacenados en la memoria de sólo lectura lugares. Significa, la alteración de los valores, p[1] = 's' no está permitido. Sin embargo, el puntero p1 no es const, por lo que puede ser re-asignado a un nuevo valor p1="EFG"; con razón.

    • ¿cómo responder a la pregunta.?
    • Por ejemplo, como para mí, entonces no he entendido la pregunta.:)
    • Gracias, pero lo tengo asignado a la dirección «ABCD» para ?! es la dirección de la sth que el programador no sabe ?!
    • ¿cómo es no? Por favor, hágamelo saber lo que otra persona está cant.
    • el la dirección de la base de «ABCD» cadena es asignado a p1.
    • Gracias, así que ¿por qué las pilas de desbordamiento cuando escribo : printf («%s»,*p1); ?! no es sólo la impresión de «Una» ?!
    • usted debe escribir printf ("%s",p1); La %s especifica una cadena de puntero: usted ha dado el primer carácter de la cadena.
    • aviso de la mención de null-terminated terminología. esa es la señal de final de la cadena, es decir, hasta que la parte printf() se va a imprimir.
    • La veleta sí tienes razón, gracias . así que escribí printf («%c»,*p1); y el impreso «E», pero yo esperaba ver «a» basados en las respuestas …
    • espero que te refieres a la del caso 1. entonces;s correcto, porque la dirección de la base de la «ABCD», se sustituye por la dirección de la base de «EFG» ahora [por p1="EFG";], y el primer carácter es, de hecho,E.
    • Ghosh Tan *p1 es siempre el [0] bloqueo de la dirección , y como usted puede cambiar la dirección , puede cambiar *p1[0] … estoy en lo cierto ?
    • sí, en esto caso, tienes razón. compruebe también la actualización en mi respuesta. He ampliado un poco.
    • puede cambiar *p1[0]« … casi correcta, pero *p1[0]sería una matriz de punteros. Para cambiar el primer elemento de la cadena (aparte del hecho de que no se debe cambiar una cadena literal) de cambiar *p1 o p1[0]. Para cambiar el segundo elemento de la cadena de cambiar *(p1+1) o p1[1].
    • A la derecha está, que pasé por alto. En este caso, o bien p1[0] o *p1 para el primer elemento.

  5. 1
    int main()
    {
        char *p1="ABCD";
        p1="EFG";
        printf ("%s",p1);
        return 0;
    }

    Esto es la falta de la necesaria #include <stdio.>. Sin ella, el compilador podría permitirle salirse con la llamada printf, pero esto no está garantizado para trabajar. Y un punto menor: int main() debe ser int main(void).

    De hecho, hay mucho sucediendo en este programa, y parte de ella es bastante sutil.

    char *p1 = "ABCD";

    "ABCD" es un literal de cadena. Especifica un anónimo array de objetos de tipo char[5] (4 para los caracteres especificados, más 1 para el '\0' carácter nulo que marca el final de la cadena). Que objeto tiene almacenamiento estático duración, lo que significa que existe durante toda la ejecución del programa (a diferencia de una variable local, por ejemplo, que deja de existir cuando se sale del ámbito (que es una simplificación)).

    Una matriz de expresión es, en la mayoría de los contextos, convierte de forma implícita a un puntero a su primer elemento. Así p1 se inicializa a punto para el personaje 'A', el primer carácter de anónimo objeto de matriz.

    p1 debe ser definida como const char *p1 = .... En realidad, no es necesario, pero ayudará a que el compilador de detectar cualquier intento de modificar el objeto de matriz. (El objeto no es const, pero modificando tiene un comportamiento indefinido.)

    p1 = "EFG";

    Ahora el valor almacenado en p1 está fuera demolido y reemplazado por un nuevo valor de puntero, esta vez apuntando a la 'E' de la cadena literal "EFG". (Así que no había ningún punto en inicializarla, pero eso está bien.)

    printf("%s", p1);

    Aquí pasamos el valor de p1 (un valor de puntero) a la printf función.

    En este punto, el valor de *p1 es 'E', y es de tipo char. Pero printf es capaz de imprimir toda la cadena "EFG". Utiliza aritmética de punteros para hacerlo. En algún lugar de la aplicación de printf, hay un bucle que toma el valor de puntero que se pasa, elimina referencias para obtener el valor del carácter a imprimir, y luego se incrementa el puntero de modo que apunte a la siguiente carácter de la cadena ('F'). Este bucle continúa hasta que se alcanza el '\0' carácter nulo que marca el final de la cadena; que el carácter nulo no se imprime.

    Puesto que las matrices son en un sentido de «ciudadanos de segunda clase» en C, la mayoría de las operaciones sobre los objetos de la matriz se hace de esta manera, el uso de punteros a los elementos de la matriz para recorrer la matriz. (También puede utilizar la indexación de la notación arr[i], que es esencialmente la misma cosa.) printf no tiene acceso directo a la matriz objeto de la misma; se basa en el puntero (a su primer elemento) para determinar que la matriz está en la memoria, y en el '\0' terminator para determinar donde los extremos de una cuerda.

    El segundo programa es el mismo, excepto que p1 no es reasignado, por lo que la cadena de "ABCD" se imprime.

    La relación entre las matrices y punteros en C puede ser confuso. La sección 6 de la comp.lang.c FAQ hace un muy buen trabajo de explicar.

  6. 1

    No entiendo es lo que exactamente *p1 es ?

    Es un número de una dirección que contiene un valor char ? Es un char ?

    Si usted está hablando acerca de *p1 en la declaración

    char *p1 = "ABCD";    

    luego * indica que p1 es un puntero a char (de hecho const char en este caso). p1 sólo apunta al primer carácter de la cadena literal ABCD.

    Si usted se está preguntando acerca de *p1 como en

    printf("%c", *p1); 

    luego * aquí es un operador de indirección y *p1 significa que el valor del carácter p1 puntos, a los que se A. *p1 es equivalente a p1[0].

    La declaración de

     p1 = "DEF";  

    vamos a p1 punto hasta el primer carácter de la cadena literal DEF.

    ¿Por qué es const ?

    Literales de cadena se almacenan en sólo lectura sección de la memoria.

    char *p1 = "ABCD";  

    es equivalente a

    char const *p1 = "ABCD";

    Esto significa que no se puede modificar un literal de cadena.

    *p1 = 'a'; //WRONG. Invokes undefined behavior.  
  7. 0

    El punto de que yo no entiendo es lo que exactamente *p1 es ! es un número de una dirección que contiene un valor char ? es un char ? lo que está en *p1 ahora ?

    El tipo de *p1 es char. Su valor es el carácter 'A'.

    ¿por qué es const ?

    Literales de cadena, como "ABCD", se colocan en la memoria de sólo lectura. La modificación de ellos a través de p es la causa de un comportamiento indefinido. Es por eso que *p1 es de sólo lectura, es decir, es un const.

  8. 0

    El punto de que yo no entiendo es lo que exactamente *p1 es ! es un número de una dirección que contiene un valor char ? es un char ? lo que está en *p1 ahora ?

    El valor de *p1 es p1[0], que es un char de valor 'E' en su primer programa y de valor 'A' en su segundo programa.

    ¿por qué es const ?

    No es const en C (es en C++), pero los literales de cadena se especifican a ser no modificables en C que significa un intento de modificar *p1 invoca un comportamiento indefinido.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein