Fgets () возвращает NULL с коротким буфером, совместимым?
В модульном тестировании функция, содержащаяfgets()
наткнулся на неожиданный результат при размере буфераn < 2
, Очевидно, что такой размер буфера глуп, но тест исследует угловые случаи.
Упрощенный код:
#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;
}
Что удивительно в том, чтоfgets()
возвращаетсяNULL
а такжени feof()
ниferror()
являются1
.
Спецификация C, ниже, кажется, молчит об этом редком случае.
Вопросы:
ВозвращаетсяNULL
без настройкиfeof()
ниferror()
уступчивое поведение?Может ли другой результат быть совместимым поведением?Имеет ли это значение, еслиn
равно 1 или меньше 1?Платформа: gcc версия 4.5.3 Цель: i686-pc-cygwin
Вот выдержка из Стандарта C11, некоторые акценты мои:
7.21.7.2fgets
функция
fgets функция читает не более, чем на число символов, указанноеn [...]
fgets функция возвращаетs если успешно. Если обнаружен конец файлаа также в массив не было прочитано ни одного символа, содержимое массива остается неизменным и возвращается нулевой указатель. Если во время операции возникает ошибка чтения, содержимое массива неопределенное и возвращается нулевой указатель.
Связанные сообщения
Как использовать feof и ferror для fgets (мини-оболочка в C)
Проблема создания оболочки в C (Seg-Fault и ferror)
fputs (), fgets (), ferror () вопросы и эквиваленты C ++
Возвращаемое значение fgets ()
[Редактировать] Комментарии к ответам
@Shafik Yaghmour хорошо представил общую проблему: поскольку в спецификации C не упоминается, что делать, когда он не читаетлюбой данные ни писатьлюбой данные дляs
когда (n <= 0
), это неопределенное поведение. Таким образом, любой разумный ответ должен быть приемлемым, например, возвратNULL
, не устанавливайте флаги, оставляйте буфер в покое.
Что должно произойти, когдаn==1
, Ответ @Oliver Matthews и комментарий @Matt McNabb указывают на недостаточную ясность спецификации C с учетом буфераn == 1
, Спецификация Cкажется в пользу буфераn == 1
должен вернуть указатель буфера сs[0] == '\0'
, но не достаточно явно.