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 enputs(argv[1]);
mientras queprintf("%s", argv[1]);
Todavía invocaprintf()
.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.