Небезопасно ли передавать unsigned long функции, которая использует long?

Предисловие: мне не разрешено использовать какие-либо функции из библиотеки 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");

Проблема в том, что ваша функция небезопасна для использования с подписанным long: D

Antti Haapala -- Слава Україні 18.12.2020 17:21

Просто используйте sprintf(). Это, по крайней мере, безопасно для многопоточности, чего нет в опубликованной вами функции. Черт возьми, тот, который вы разместили, небезопасен в том смысле, что последующее использование сотрет значение предыдущего использования.

Andrew Henle 18.12.2020 17:21

Этот вопрос сводится к тому, «безопасно ли преобразовывать целое число без знака в знаковое» (если игнорировать посторонние вопросы). Ответ можно найти в стандарте C port70.net/~nsz/c/c11/n1570.html#6.3.1.3 (Иначе новый тип является знаковым и значение не может быть представлено в нем; либо результат сигнал, определяемый реализацией, или сигнал, определяемый реализацией.)

Eugene Sh. 18.12.2020 17:22

Что бы это ни стоило, эта функция просто битком набита «Что?? Нет!» моменты. Если цель состоит в том, чтобы преобразовать число в строку, используйте существующую библиотечную функцию. Эта проблема была решена десятилетия назад и есть в стандартной библиотеке.

tadman 18.12.2020 17:46

Почитайте snprintf, потому что этот код требует реального разговора и вмешательства. %xl делает то, что вы хотите, а затем некоторые.

tadman 18.12.2020 17:48

У меня есть проект, который заставляет меня перекодировать метод printf. Мне не разрешено использовать стандартную библиотеку C. Я должен кодировать все сам.

Jules 18.12.2020 17:50
If yes how can I make it work ? Напишите отдельную функцию для unsigned long. val = (unsigned long)va_arg(*list, void *); Я не верю, что это правильный код или что он делает то, что вы думаете. Ваша функция сильно сломается с отрицательными числами.
KamilCuk 18.12.2020 17:56
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
7
452
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
Небезопасно ли передавать 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.

Jules 19.12.2020 01:02

Другие вопросы по теме