¿Es fgets () devuelve NULL con un búfer corto compatible?
En la unidad que prueba una función que contienefgets()
, se encontró con un resultado inesperado cuando el tamaño del búfern < 2
. Obviamente, un tamaño de búfer de este tipo es una tontería, pero la prueba está explorando casos de esquina.
Código simplificado
#include <error.h>
#include <stdio.h>
void test_fgets(char * restrict s, int n) {
FILE *stream = stdin;
s[0] = 42;
printf("< s:%p n:%d stream:%p\n", s, n, stream);
char *retval = fgets(s, n, stream);
printf("> errno:%d feof:%d ferror:%d retval:%p s[0]:%d\n\n",
errno, feof(stream), ferror(stream), retval, s[0]);
}
int main(void) {
char s[100];
test_fgets(s, sizeof s); // Entered "123\n" and works as expected
test_fgets(s, 1); // fgets() --> NULL, feof() --> 0, ferror() --> 0
test_fgets(s, 0); // Same as above
return 0;
}
Lo sorprendente es quefgets()
devolucionesNULL
yninguno feof()
niferror()
son1
.
La especificación C, a continuación, parece silenciosa en este caso raro.
Preguntas:
Esta volviendoNULL
sin establecerfeof()
niferror()
comportamiento conforme?¿Podría un resultado diferente ser un comportamiento conforme?¿Hay alguna diferencia sin
es 1 o menos de 1?Plataforma: gcc versión 4.5.3 Objetivo: i686-pc-cygwin
Aquí hay un resumen del Estándar C11, algo de énfasis mío:
7.21.7.2 Elfgets
función
losfgets la función lee como máximo uno menos que el número de caracteres especificado porn [...]
losfgets la función vuelves si tiene éxito. Si se encuentra el final del archivoy no se han leído caracteres en la matriz, el contenido de la matriz permanece sin cambios y se devuelve un puntero nulo. Si se produce un error de lectura durante la operación, el contenido de la matriz es indeterminado y se devuelve un puntero nulo.
Publicaciones relacionadas
Cómo usar feof y ferror para fgets (minishell en C)
Problemas para crear un shell en C (Seg-Fault y ferror)
fputs (), fgets (), preguntas de ferror () y equivalentes de C ++
Valor de retorno de fgets ()
[Editar] Comentarios sobre respuestas
@Shafik Yaghmour presentó bien el problema general: dado que la especificación C no menciona qué hacer cuando no leealguna datos ni escrituraalguna datos as
cuando (n <= 0
), es un comportamiento indefinido. Por lo tanto, cualquier respuesta razonable debe ser aceptable, como la devoluciónNULL
, no establezca banderas, deje el búfer solo.
En cuanto a lo que debería suceder cuandon==1
, La respuesta de @Oliver Matthews y el comentario de @Matt McNabb indican la falta de claridad de una especificación C considerando un amortiguador den == 1
. La especificación Cparece para favorecer un búfer den == 1
debería devolver el puntero del búfer cons[0] == '\0'
, pero no es lo suficientemente explícito.