Como es mencionado por las otras respuestas NULL
no es válida para pasar a sscanf
como un argumento adicional.
http://www.cplusplus.com/reference/cstdio/sscanf dice de argumentos adicionales:
Dependiendo de la cadena de formato, la función puede esperar que una secuencia de argumentos adicionales, cada uno con un puntero de almacenamiento asignado en la interpretación de los personajes extraídos se almacena con el tipo apropiado.
For the %s
specifier these extracted characters are:
Cualquier número de caracteres no está en blanco, con parada en el primer carácter espacios que se encuentren. Un carácter nulo de terminación se agrega automáticamente al final de la secuencia almacenada.
Por lo tanto, cuando se almacenan los "caracteres que no son de espacios en blanco" y "carácter nulo de terminación", habrá una segfault. ¿Qué es exactamente lo que Visual Studio rendirá (se puede probar que esta falla en http://webcompiler.cloudapp.net/):
Ahora por lo que los compiladores no Visual Studio, el código de extracción de libc para la %s
especificador: https://github.com/ffainelli/uClibc/blob/master/libc/stdio/_scanf.c#L1376 tiene el líder comentario: /* We might have to handle the allocation ourselves */
esto es porque:
la biblioteca GNU C apoyó el especificador de conversión asignación dinámica (como una extensión no estándar) a través del carácter a
. Esta característica parece estar presente al menos desde glibc 2.0.
Desde la versión 2.7, glibc también proporciona el modificador m
con el mismo propósito que el modificador a
.
[Source]
Así pues extractos libc a un buffer construidos internamente para sscanf
y posteriormente se comprueba que el parámetro de búfer no tiene indicadores establecidos antes de asignarlo, nunca va a escribir caracteres a un parámetro NULL
búfer.
No puedo dejar de insistir en que esto no es estándar, y no se garantiza que se conserve incluso entre actualizaciones menores de la biblioteca. Un mucho mejor manera de hacer esto es utilizar el *
sub-especificador que:
indica que los datos se debe leer de la corriente pero ignorado (es decir, no se almacena en la ubicación señalado por un argumento) .
[Source]
Esto podría lograrse así por ejemplo:
s == NULL ? sscanf("Privjet mir!", "%*s") : sscanf("Privjet mir!", "%s", s);
Obviamente el verdadero-rama del ternario es un no-op, pero he incluido con la expectativa de que se esperaban otros datos para leer de la cadena.
Esta respuesta también nos enseña que la prohibición de null no necesita mencionar explícitamente la palabra "null".Establecer que algo debe ser "un puntero a" implícitamente prohíbe el nulo. –
Lii