Предисловие: мне не разрешено использовать какие-либо функции из библиотеки C
У меня есть эта функция:
char *to_base(long nbr, char *base)
{
static char buffer[50];
char *ptr;
int base_len;
ptr = &buffer[49];
*ptr = 0;
base_len = ft_strlen(base);
while (nbr != 0)
{
*--ptr = base[nbr % base_len];
nbr /= base_len;
}
return (ptr);
}
Как мы видим, это занимает много времени. В моей программе у меня есть unsigned long, который я должен перевести в его шестнадцатеричное значение. Небезопасно ли передавать unsigned long в эту функцию? Если да, то как я могу заставить его работать?
РЕДАКТИРОВАТЬ : Вот как я его сейчас использую:
unsigned long val;
char *hexa;
val = (unsigned long)va_arg(*list, void *);
hexa = to_base(val, "0123456789abcdef");
Просто используйте sprintf(). Это, по крайней мере, безопасно для многопоточности, чего нет в опубликованной вами функции. Черт возьми, тот, который вы разместили, небезопасен в том смысле, что последующее использование сотрет значение предыдущего использования.
Этот вопрос сводится к тому, «безопасно ли преобразовывать целое число без знака в знаковое» (если игнорировать посторонние вопросы). Ответ можно найти в стандарте C port70.net/~nsz/c/c11/n1570.html#6.3.1.3 (Иначе новый тип является знаковым и значение не может быть представлено в нем; либо результат сигнал, определяемый реализацией, или сигнал, определяемый реализацией.)
Что бы это ни стоило, эта функция просто битком набита «Что?? Нет!» моменты. Если цель состоит в том, чтобы преобразовать число в строку, используйте существующую библиотечную функцию. Эта проблема была решена десятилетия назад и есть в стандартной библиотеке.
Почитайте snprintf, потому что этот код требует реального разговора и вмешательства. %xl делает то, что вы хотите, а затем некоторые.
У меня есть проект, который заставляет меня перекодировать метод printf. Мне не разрешено использовать стандартную библиотеку C. Я должен кодировать все сам.
If yes how can I make it work ?
Напишите отдельную функцию для unsigned long
. val = (unsigned long)va_arg(*list, void *);
Я не верю, что это правильный код или что он делает то, что вы думаете. Ваша функция сильно сломается с отрицательными числами.
Небезопасно ли передавать unsigned long в эту функцию?
Это «безопасно», так как программа не отформатирует ваш жесткий диск и не начнет новую мировую войну.
Передаваемые аргументы функции преобразуются в тип аргумента. Беззнаковое значение будет преобразовано в знаковое. Все современные архитектуры используют дополнение до двух, результат легко предсказать. Ваш компилятор должен задокументировать поведение, например. в реализация gcc определила поведение:
Результат или сигнал, вызванный преобразованием целого числа в целочисленный тип со знаком, когда значение не может быть представлено в объекте этого типа (C90 6.2.1.2, C99 и C11 6.3.1.3).
Для преобразования в тип ширины N значение уменьшается по модулю 2^N, чтобы быть в пределах диапазона типа; сигнал не поднимается.
«уменьшено по модулю 2 ^ N» - в основном 2 ^ N вычитается до тех пор, пока значение не окажется в пределах диапазона. Итак, если у вас есть 32-битные long и (long)(unsigned long)4294967196ul, вы вычитаете 2 ^ 32 из значения, и оно равно (long)-100.
Если да, то как я могу заставить его работать?
Правильно обрабатывать отрицательные числа.
И написать отдельную функцию для беззнаковых и знаковых чисел.
Также (unsigned long)va_arg(*list, void *); приводит значение указателя void* к unsigned long (?). Скорее всего вы хотите va_arg(list, unsigned long) - взять unsigned long из аргументов.
Я перекодирую функцию printf и использую формат %p. Вот почему я использую va_arg(list, void*) для получения адреса указателя. Мне сказали затем использовать его как unsigned long.
Проблема в том, что ваша функция небезопасна для использования с подписанным long: D