2016-08-02 2 views
11

функции, такие как strcpy(), malloc(), strlen() и различные другие принимают их аргументы или возвращаемые значения как size_t вместо int или unsigned int по очевидным причинам.Почему fgets принимает int вместо size_t?

Некоторые функции файла, такие как fread() и fwrite(), используют size_t. В добавлении, было бы предположено что char* fgets (char *str, int num, FILE *stream) должно использовать size_t, а не int как аргумент для своего размера буфера.

Однако fgets() использует int. Есть ли объективное объяснение, почему?

+12

В стандартной библиотеке C отсутствует согласованность. С течением времени функции эволюционировали. 'size_t', возможно, не существовало, когда был введен« fgets »(просто моя догадка). – user694733

+1

https://groups.google.com/forum/#!topic/comp.std.c/FnENEIlCidg – artm

+3

Истерические изюм. Вероятно, ранняя реализация (до стандартизации) использования «int» и ее продолжение для «совместимости» при стандартизации C. И я голосую, чтобы закрыть как * основанное на мнениях *. –

ответ

9

Оригинал K & R определено fgets() на стр.155 с аргументом int. Код, представленный в книге, работал бы с unsigned int (он использует >0, но цикл написан так, чтобы он никогда не опускался ниже нуля).

size_t введено позже, в C89 (ANSI C), как тип sizeof(). Поскольку эта функция была специально введена для согласования распределения памяти, соответственно обновлялись функции управления и строковые функции. Но файловый ввод-вывод не был: единственными файловыми функциями, которые использовали size_t в C89, являются те новые , введенные C89 и не существовавшие в K & R, такие как, например, fread()/fwrite(). Да, K & R не имел этих функций и полагался только на операции с блоком только на (не переносные) функции чтения/записи unix с использованием дескрипторов файлов.

Следует отметить, что POSIX standard, который гармонизировал функции unix, был разработан параллельно с стандартом ANSI C и issued late 1988. Этот стандарт гармонизировал многие функции unix для использования size_t, так что read()/write() в настоящее время определены с помощью size_t. Но для стандартных функций библиотеки C, таких как fgets(), POSIX дает преимущество в C стандартной (формулировки текущей версии стандарта):

функциональных возможностей, описанных на этой справочной странице совмещен со стандартом ISO C , Любой конфликт между описанными здесь требованиями и стандартом ISO C является непреднамеренным.

Таким образом, в стандарте POSIX также, как ни странно, до сих пор fgets() унаследовал от своего исторического K & R int.


Edit: дополнительное чтение

STDIO.h: Этот заголовок определяет и прототипы большинства функций, перечисленных в главе 7 K & R. Немногие, если таковые имеются, были внесены изменения в определениях , найденные в K & R, но было добавлено несколько новых функций.

+0

Есть ли у вас какие-либо идеи, предсказуемо ли какие-либо заметные пре-C89 реализации fgets, когда они передаются отрицательное значение (например, предсказуемо рассматривая его как ноль, предсказуемо ничего не делая, считывая -N байтов данных, но опуская новую строку и т. д.]? Если это так, изменение в size_t может запретить реализации из поддержки этой функции, если только длина не была ограничена SIZE_T_MAX-UINT_MAX [из того, что я могу сказать, длина передачи, превышающая размер буфера, определяется поведением, если новая строка успешно прочитана до конца буфер]. – supercat

+1

Реализация K & R датируется с 1978. Поскольку это целое число со знаком, а первое условие цикла - '--n> 0', оно останавливается и помещает нулевой ограничитель в буфер. Так что вполне предсказуемо. Если параметр был неподписанным, один и тот же код может вызвать переполнение буфера, но будет останавливаться после максимальной итерации UINT_MAX (если аппаратное обеспечение не будет захватить переброску знакового бита). Тогда могли бы быть и другие реализации: pre 89 было много компиляторов, большинство из которых уже не известны сегодня ;-). – Christophe

+0

@supercat Я мог найти мой бывший компилятор Lattice C 1986 года ([приобретенный Microsoft] (https://en.wikipedia.org/wiki/Lattice_C)) с источником его стандартной библиотеки. 'fgets()' реализуется с помощью 'for (i = 0; i Christophe

Смежные вопросы