_IO_getc_unlocked
- это встроенный макрос.Идея состоит в том, что вы можете получить символ из потока, не вызывая функцию, что делает его достаточно быстрым для использования в тесных циклах и т. Д.
Давайте разберем его по одному слою за раз.Во-первых, что такое _IO_BE
?
/usr/include/libio.h:# define _IO_BE(expr, res) __builtin_expect ((expr), res)
_IO_BE является подсказкой для компилятора, что expr
будет обычно оценивать как res
.Он используется для структурирования потока кода, чтобы быть быстрее, когда ожидание истинно, но не имеет другого семантического эффекта.Таким образом, мы можем избавиться от этого, оставив нам:
#define _IO_getc_unlocked(_fp) \
( ( (_fp)->_IO_read_ptr >= (_fp)->_IO_read_end ) \
? __uflow(_fp) : *(unsigned char *)(_fp)->_IO_read_ptr++) )
Давайте превратим это в встроенную функцию для ясности:
inline int _IO_getc_unlocked(FILE *fp) {
if (_fp->_IO_read_ptr >= _fp->_IO_read_end)
return __uflow(_fp);
else
return *(unsigned char *)(_fp->_IO_read_ptr++);
}
Короче, у нас есть указатель на буфери указатель на конец буфера.Мы проверяем, находится ли указатель вне буфера;если нет, мы увеличиваем его и возвращаем тот символ, который был при старом значении.В противном случае мы вызываем __uflow
для повторного заполнения буфера и возврата вновь прочитанного символа.
Таким образом, это позволяет нам избежать накладных расходов при вызове функции до тех пор, пока нам фактически не потребуется IO для повторного заполнения входного буфера.
Имейте в виду, что стандартные библиотечные функции могут быть такими сложными;они также могут использовать расширения языка C (такие как __builtin_expect
), которые НЕ являются стандартными и могут НЕ работать на всех компиляторах.Они делают это потому, что должны быть быстрыми, и потому что они могут делать предположения о том, какой компилятор они используют.Вообще говоря, ваш собственный код не должен использовать такие расширения без крайней необходимости, так как это затруднит перенос на другие платформы.