выглядит как _IO_vfprintf
- скрытый псевдоним _IO_vfprintf_internal
.
При компиляции файла vfprintf.c
file для обычных (не широких) символов fprintf
становится макросом, определенным как _IO_vfprintf_internal
, с здесь и неопределенным до наложения псевдонима здесь .
Итак, _IO_vfprintf_internal
объявление начинается здесь , где vfprintf
объявлено (ну, «в необработанном исходном файле», идентификатор vfprintf
get никогда не объявляется).
После того, как функции vfprintf
прекратили обработку всех значений ширины, пробелов, минусов и других спецификаторов формата, он, наконец, будет перебирать таблиц перехода (что по сути является умным способом перехода к различным goto
метки в таблице переходов с адресами, полученными с помощью расширений GCC метки в качестве значений ), они будут помещены на метку form_integer:
. Оттуда мы прыгаем до number:
. Оттуда мы называем _itoa_word
.
Теперь _itoa_word просто и легко, даже достаточно, чтобы разместить здесь предварительно обработанную функцию:
char *
_itoa_word (_ITOA_WORD_TYPE value, char *buflim,
unsigned int base, int upper_case) {
const char *digits = (upper_case
? _itoa_upper_digits
: _itoa_lower_digits);
...
switch (base)
{
...
// SPECIAL (10); expands to:
case 10:
do
*--buflim = digits[value % Base];
while ((value /= Base) != 0);
break;
...
}
...
}
Где digits
, как в _itoa_upper_digits или как в _itoa_lower_digits - это простая таблица поиска, массив символов, инициализированный из строкового литерала, используемый для преобразования десятичных дробей в соответствующие им представление ascii.
После _itoa_word
есть некоторый код для обработки выравнивания по левому краю строки, печати символа начального знака и заполнения строки пробелами или нулями, но в итоге наша строка получает выведено (или выравнивание по левому краю выводимый ). * * тысяча пятьдесят девять
пример преобразования целых чисел в строку
Так что 99% работы - для обработки всего странного
printf("%+- 3lld %+- 4.3Lf %-+04hhd %+- 5zd", 1llu, 2.L, 3, (ssize_t)4);
спецификаторы формата, которым он должен соответствовать. Преобразование - это просто простое преобразование с использованием строки поиска (для обработки не-ASCII-систем), которая работает в обратном направлении через число:
#include <stdio.h>
char *my_itoa(char *dest, size_t destlen, int number)
{
// we will work our way from the ending
char *p = &dest[destlen];
// null terminate the string
*--p = '\0';
while (number) {
if (p == dest) {
// destination buffer too small!!
return NULL;
}
*--p = "0123456789"[number % 10];
number /= 10;
}
return p;
}
int main()
{
char buf[20];
printf("%s\n", my_itoa(buf, sizeof(buf), 123));
}