¿Por qué no necesito desreferenciar un puntero de carácter en C antes de imprimirlo?

¿Por qué funciona este código? Espero que tenga que desreferenciar ptr , printf("%s\n", *ptr); antes de que pudiera imprimirlo, pero me sale una Segmentation Fault si trato de hacerlo de esa manera.

 #include  int main(int argc, char *argv[]) { char name[] = "Jordan"; char *ptr = name; printf("%s\n", ptr); } 

Espero que ustedes me puedan dar una idea.

Cuando imprime una cadena necesitamos la dirección inicial de la cadena.

 printf("%s\n", ptr); ^ address with %s 

Imprime los caracteres hasta el encuentro nulo.

Mientras que para imprimir chat int .. necesitamos valor variable :

 printf("%c\n", *ptr); ^ * with %c print first char 

Donde, como en scanf() una cadena siempre necesitas dar una dirección:

 scanf("%s", ptr); ^ string address 

También para int scanf() a char

 scanf("%c", ptr); ^ read at first location char address 

Nota: Scanf() necesita una dirección con %c para almacenar un valor escaneado en la memoria.

Tenga cuidado, su ptr apunta a una cadena constante para que no pueda usar en scanf .

¿Por qué falla la segmentación con el siguiente código?

  printf("%s\n", *ptr); 

Cuando hace esto, debido a que %s printf interpreta *ptr como una dirección, pero en realidad no es una dirección y si la trata como una dirección, señala a una ubicación que está protegida por lectura para su progtwig (proceso). Fallo de segmentación.

Su ptr vía name apunta a una cadena constante en la memoria (“Jordan”) como se muestra en el siguiente diagtwig:

 name 2002 ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │ 'J' │ 'o' │ 'r' │ 'd' │ 'a' │ 'n' │'\0' │ ........ └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ ^ | ptr = name ==> ptr = 2002 *ptr = 'J' 

En printf("%s\n", *ptr); la *ptr = 'J' y el valor ASCII de char ‘J’ es 74 pero la dirección 74 no está bajo su control de proceso y está intentando leer desde esa ubicación de memoria y es una falla de segmentación y violación de memoria.

Si comstack su código que contiene printf("%s\n", *ptr); luego, con la opción adecuada, diga -Wall con GCC obtendrá una advertencia como la siguiente:

warning: format '%s' expects argument of type 'char *', but argument 2 has type 'int'

Dice que %s necesita (espera) una dirección de tipo char* pero está poniendo valor

darse cuenta:

 printf("%s\n", *ptr); ^ ^ argument-2 argument-1 

Esto se debe a que el especificador de formato %s en la cadena de formato que pasa a printf significa que el argumento correspondiente debe ser una cadena, no un solo carácter. Y en C, una cadena es un puntero al principio de un bloque de caracteres que tiene un carácter nulo (byte con un valor de 0) al final.

Básicamente, esto funciona porque estás haciendo exactamente lo que se supone que debes hacer para imprimir una cadena.

El especificador de formato %s le dice a printf que espere un puntero a una matriz de caracteres terminada en nulo. Que es lo que son name y ptr .

*name y *ptr no lo son. Si los elimina, obtendrá una única char , que básicamente es mentira a printf , lo que resulta en un comportamiento indefinido.

El formateador de %s para printf espera una “cadena”, que en realidad es un puntero a una matriz de caracteres terminada en nulo.

Es decir, printf espera que le pases el puntero. Cuando eliminas la referencia al puntero, toma la letra J, cuyo valor en ascii es 74 (decimal), e intenta tratarlo como un puntero a una matriz. Esa es un área de la memoria que es inaccesible, por lo que obtiene la violación de segmentación.

*ptr es esencialmente una referencia a un solo char , no a la cadena de caracteres. Debido a este char * y char[] son esencialmente lo mismo

Cuando declara char prt = nombre, es donde se le hace una referencia. el “ ” aquí no es parte de la variable, solo una forma de mostrar que desea lo que señala esa variable. Si tuviera que volver a poner el * prt en su printf, lo hará dos veces. name es una matriz de caracteres y * ptr es un puntero a los que no se ha referenciado.

Espero que la explicación ayude 🙂