Что происходит, когда я передаю 0 в качестве второго параметра getline? - PullRequest
4 голосов
/ 24 мая 2019

cplusplus.com утверждает, что вторым параметром функции getline является

Максимальное количество символов для записи в s

ОднакоЯ видел такой код:

size_t linecap = 0;
ssize_t linelen;
linelen = getline(&line, &linecap, fp);

Разве это не будет читать 0 байтов из источника?Или что-то еще происходит?

Ответы [ 2 ]

6 голосов
/ 24 мая 2019

Нет, это не правильно. Из справочной страницы , ( выделено мое )

Если *lineptr равно NULL, то getline() выделит буфер для хранения строки, который должен быть освобожден программой пользователя. (В этом случае значение в *n игнорируется.)

В качестве альтернативы, перед вызовом getline(), *lineptr может содержать указатель на выделенный malloc (3) буфер размером *n байт. Если буфер недостаточно велик для размещения строки, getline() изменяет ее размер с помощью realloc(3), обновляя *lineptr и *n при необходимости.

В любом случае при успешном вызове *lineptr и *n будут обновлены с учетом адреса буфера и назначенного размера соответственно.

Итак, начальное значение, сохраненное в памяти, на которое указывает второй аргумент, не влияет на фактическое сканирование. После того, как значение отсканировано и заполнено в буфер,

  • возвращаемое значение функции сообщит вам размер отсканированного ввода в байтах.
  • значение *n сообщит вам размер буфера, который был выделен для хранения ввода (который обычно больше, чем размер отсканированного ввода).
3 голосов
/ 24 мая 2019

Идея getline заключается в том, что перераспределений как можно меньше, поскольку вызовы malloc, как правило, дороги. Следовательно, если вы будете многократно использовать getline для чтения строк в файле, используя один и тот же буфер и длину, буфер будет в конечном итоге увеличен до размера самой длинной строки в файле, и для последующих строк не потребуется перераспределение самая длинная линия.

Но для того, чтобы это работало, должны соблюдаться определенные контракты, а именно, если *lineptr равно не NULL , то оно

  • должен быть указателем, возвращаемым malloc
  • должен иметь размер выделения не менее *n байтов

Следствие: прохождение 0 в *n в порядке при следующих двух обстоятельствах:

  • , если *lineptr равно NULL
  • *lineptr - это любой живой указатель, возвращаемый malloc (так как любой указатель, возвращаемый malloc, будет иметь пространство в 0 байт).

в обоих случаях *n будет обновлено до длины строки, а возвращаемое значение realloc(*lineptr, new_line_length_with_terminator) (в случае успеха) будет присвоено *lineptr.

Конечно

...