variable float c linux printf

c - float - printf java



Agregar un carácter de nueva línea a printf() cambia el comportamiento del código (3)

Ambos son comportamientos indefinidos , por lo que una respuesta podría detenerse aquí.

Pero hay al menos una explicación para la salida de (null) . Esta es una extensión en glibc (la biblioteca C de GNU). Pasar 0 para %s en printf() se considera indefinido en el estándar C y, por lo tanto, podría resultar en un bloqueo . Los desarrolladores de glibc decidieron hacer algo significativo en su lugar.

Sin embargo, la razón por la que la segunda falla es que con la nueva línea, el compilador decide optimizar : En lugar de printf("%s/n", argv[1]) , ejecuta el puts(argv[1]) , que es semánticamente equivalente según Al estándar C, por lo tanto, una optimización permitida. Pero glibc s "(null) -trick" solo se implementa en printf() .

Hay otro comportamiento indefinido en su programa: potencialmente accede a argv fuera de los límites . No hay garantía de qué valor encontrará en argv[i] cuando i > argc . Existe una pequeña posibilidad de que argc pueda ser 0, por lo que también podría experimentar cualquier otra cosa .

Por alguna razón, agregar /n a printf() cambia el comportamiento del siguiente código. El código sin /n imprime (null) mientras que el código con /n produce un Segmentation fault .

Printf.c

#include <stdio.h> int main(int argc, char* argv[]){ printf("%s", argv[1]); }

Printf.c - Salida

$ gcc -o Printf Printf.c $ ./Printf (null)

Printf_Newline.c

#include <stdio.h> int main(int argc, char* argv[]){ printf("%s/n", argv[1]); }

Printf_Newline.c - Salida

$ gcc -o Printf_Newline Printf_Newline.c $ ./Printf_Newline Segmentation fault (core dumped)

Tengo curiosidad por entender la razón detrás de esto.


El código tiene un comportamiento indefinido en ambos casos si el programa no recibe ningún argumento de línea de comando, por lo que cualquier cosa puede suceder.

Ya que eres curioso (¡bueno para ti!), Aquí hay una explicación potencial para lo que observas:

  • printf("%s/n", argv[1]); puede ser optimizado por el compilador en puts(argv[1]); mientras que printf("%s", argv[1]); Todavía invoca printf() .

  • algunas implementaciones de printf aceptan un puntero nulo como argumento para la conversión %s , de ahí la salida (null) .

  • puts() tiene un comportamiento indefinido para un puntero nulo, en su caso una falla de segmentación.

Intente compilar ambos sin ninguna optimización ( -O0 ) y vea si obtiene un resultado (null) con y sin el /n .

Puedes jugar con el explorador del compilador de godbolt y ver cómo clang cambia el comportamiento con -O0, pero no con gcc .


La ejecución sin argumentos argv[1] será un puntero NULL . Con argv[1] siendo NULL

printf("%s", argv[1]);

invocará un comportamiento indefinido.