LINUX.ORG.RU

Int в Hex, ускорить и укоротить

 ,


1

2

Можно ли заоптимизировать эту функцию?

char * intToHex(int32_t value, uint32_t up, uint32_t pre, uint32_t msize)
{
    const char * hexdigit[2] = {"0123456789abcdef",
                                "0123456789ABCDEF"};

    union itou
    {
        int32_t  i;
        uint32_t u;
    };

    union itou conv;
    conv.i = value;

    uint32_t pos = 0;
    char * result;
                                    /* 0x    FF FF FF FF         \0 */
    if (!(result = malloc(sign(pre) * 2 + sizeof(uint32_t) * 2 + 1)))
        return 0;

    if (pre)
    {
        strcpy(result, "0x");
        pos = 2;
    }

    while (1UL << (msize * 4) > conv.u)
    {
        result[pos++] = '0';
        msize--;
    }

    while (conv.u != 0)
    {
        result[pos++] = hexdigit[sign(up)][conv.u & 0xF];
        conv.u >>= 4;
    }

    result[pos] = '\0';

    return result;
}

★★

Последнее исправление: cetjs2 (всего исправлений: 1)
Ответ на: комментарий от Eddy_Em

я его не понимаю. то проверка ничего не даст, то маллок не гарантирует выделение (при этом, если не выделит, возвращая нул)...

anonymous
()
Ответ на: комментарий от sambist

Как поправить?

Я пример зачем приводил? В обратном порядке, ясен пень, выводить.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от anonymous

Да, он самый. Его банят постоянно, поэтому сложно выявлять новые логины. Но последнее время он просто цифирки к карблогу добавляет.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

А мне жалко лишние килобайты.

Моя недо-RT-OS рабоатает на 512 байт рама. (atmega8) И я использую libc. Продолжай дальше экономить негативные байты. =)

beastie ★★★★★
()
Ответ на: комментарий от beastie

Ну, у меня все есть мечта избавиться нафиг от SPL для STM32, но уж больно у них периферия обширная, пару тысяч страниц даташита... Вот с STM8 все просто: я и заголовочный файл с дефайнами регистров сам делал.. Но таки архитекрутка-то разная.

Я себе для опытов сейчас купил десяток STM32F030. Самые дешевые 32-битные контроллеры. Жаль, на ибее еще нет 042 или 072 — они только-только появились. Но вообще чудные: с USB!

Хотя, конечно, иногда нужно не Cortex-M0, а хотя бы четверочку.

// Странно, что общаешься здесь ты, а хамло подчистил Pinkbyte. И зачем-то удалил беднягу Царя.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Off: Царя я не трогал, он и в самом деле почти перестал ругаться. (Хотя бы не из под анонимуса.) — Всё жду, когда же царь царя в голове обретёт. Но видимо ещё рано радоваться.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от beastie

Ладно - я тебя прощаю.

он и в самом деле почти перестал ругаться.

На этой реге я вообще почти не ругался, но какбэ не помогает от крысабана.

Я уже спрашивал - почему модерам можно банить в крысу, без указания постов к бану. Тут же есть система скора. Ты удаляешь - скор снимается, вешаешь -скор за темы, комменты. Скорр опустился ниже нуля - забанили.

Это чистый произвол низачто. Похоже тут уже никто не следит за модераторами. Тотальная коррупция, стукачество.

Всё жду, когда же царь царя в голове обретёт.

Царь сам себе Царь. Я не буду потакать анскиллу ради вашего спокойствия. Или мне надо соглашаться с каждым даунизмом, если в него верят 95%? Это уже секта и тотальный культ анскилла.

anonymous
()
Ответ на: комментарий от anonymous

Ты уже смог написать нетормозящую складывалку чисел, царь?

anonymous
()
Ответ на: комментарий от Eddy_Em

В общем вот, что в конце-концов получилось:

char * intToHex(int32_t value, uint32_t up, uint32_t pre, uint32_t msize)
{
    if (msize > 8)
        msize = 8;

    const char * hexdigit[2] = {"0123456789abcdef",
                                "0123456789ABCDEF"};
    union itou
    {
        int32_t  i;
        uint32_t u;
    };

    union itou conv;
    conv.i = value;

    uint32_t pos   = 0;
    int32_t  upsgn = sign(up);
    char * result;
                                    /* 0x    FF FF FF FF         \0 */
    if (!(result = malloc(sign(pre) * 2 + sizeof(uint32_t) * 2 + 1)))
        return 0;

    if (pre)
    {
        result[0] = '0';
        result[1] = 'x';
        pos = 2;
    }

    while (1UL << ((msize + 1) * 2) > conv.u)
    {
        result[pos++] = '0';
        msize--;
    }

    uint32_t i = pos + ceil(log10(conv.u) / log10(16)) - 1;
    while (conv.u != 0)
    {
        result[i--] = hexdigit[upsgn][conv.u & 0xF];
        conv.u >>= 4;
        pos++;
    }

    result[pos] = '\0';

    return result;
}

Сейчас постараюсь избавиться от массивов как у вас.

sambist ★★
() автор топика
Ответ на: комментарий от anonymous

графическая библиотека для пк.

sambist ★★
() автор топика
Ответ на: комментарий от sambist

А еще советую избавиться от объединения, не нужно оно. Число можно по указателю передавать, преобразуя в uint8_t*, тогда все будет проще.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от beastie

По старой памяти передёрнуло от "0x%x". На первой работе особо одарённые так указатели выводили.

d ★★★★
()

Конечно, printf(«%x\n», i);

anonymous
()

Лень читать тред.

  • int32 вмещает ровно 8 шестнадцатеричных цифр. Ну и +0x и \0 в конце. Т.о. можно сразу завести статический буфер и копировать его в конце функции в строку (если pre, то +2 байта от начала).
  • инициализировать '0' не нужно. Если у тебя будет 0 тетрада, туда и так попадёт '0'.
  • ИМХО вместо up лучше сразу передавать ссылку на константный массив символов. Типа intToHex(123, LowHex, ...)
  • Опять же msize... Разу уж ты завёл два массива для прописных и строчных,то почему бы не завести четыре буфера для чисел разной размерности и не передавать аргументом номер? Получится типа intToHex(123, LowHex, ..., BUF_WORD).
ziemin ★★
()
Ответ на: комментарий от anonymous

Ты лучше приведи мне десяток строк кода, который точно эту проблему воспроизведет.

Как мне сделать так, чтобы malloc вернул NULL на системе, которой не сжали яйца в тисках?

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

4.2. Я как-то тестил это, и malloc в какой-то момент мне действительно вернул NULL.

devsdc ★★
()
Ответ на: комментарий от anonymous

Прочти внимательно еще раз то, что я говорил!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от sambist
...
if (conv.u != 0)
    {
        while (1UL << ((msize + 1) * 2) > conv.u)
        {
            result[pos++] = '0';
            msize--;
        }
    }

    uint32_t i = pos + ceil(log10(conv.u) / log10(16) - 1);
    while (conv.u != 0)
    {
        result[i--] = hexdigit[upsgn][conv.u & 0xF];
        conv.u >>= 4;
        pos++;
    }
...

Исправление ошибок.

sambist ★★
() автор топика
Ответ на: комментарий от sambist
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

uint8_t f(uint32_t n) {
  uint8_t k = 0;
  if(n & 0xFFFF0000) k  = 4, n >>= 16;
  if(n & 0x0000FF00) k += 2, n >>= 8;
  if(n & 0x000000F0) k += 1, n >>= 4;
  return k;
}

char* intToHex(uint32_t value, uint32_t up, uint32_t pre, uint8_t msize)
{
  const char* hexdigit = &"0123456789abcdef0123456789ABCDEF"[up?16:0];
  char *result, *ptr;
  uint8_t n;

  msize -= 2;
  n = f(value);
  if(n < msize) n = msize;
  if(n > 7)     n = 7;

  if(pre) {
    result = malloc(2 + sizeof(value)*2 + 1);
    result[0] = '0';
    result[1] = 'x';
    ptr = result+2+n;
  } else {
    result = malloc(sizeof(value)*2 + 1);
    ptr = result+n;
  }

  ptr[1] = 0;
  switch(n) {
    case 7: *ptr-- = hexdigit[value&0xf]; value>>=4;
    case 6: *ptr-- = hexdigit[value&0xf]; value>>=4;
    case 5: *ptr-- = hexdigit[value&0xf]; value>>=4;
    case 4: *ptr-- = hexdigit[value&0xf]; value>>=4;
    case 3: *ptr-- = hexdigit[value&0xf]; value>>=4;
    case 2: *ptr-- = hexdigit[value&0xf]; value>>=4;
    case 1: *ptr-- = hexdigit[value&0xf]; value>>=4;
    case 0: *ptr-- = hexdigit[value    ];
  }

  return result;
}

int main() {
  char* t = intToHex(0x1a3f, 0, 1, 6);
  printf("%s\n", t);
  free(t);
  return 0;
}
anonymous
()
Ответ на: комментарий от Carb_blog3

Ну если написано, что malloc возвращает указатель на выделенную память, почему ты говоришь, что выделяться она будет на memset, или я чего-то не понял? Разве после маллока память не резервируется, т.е. другой 10005000й маллок не сможет дать указатель на эту же память?

momo
()
Ответ на: комментарий от Eddy_Em

Уточняй, что это поведение в линуксе. Где-нибудь ещё маллок вполне может вернуть NULL. Особенно на системах без MMU

Dark_SavanT ★★★★★
()
Ответ на: комментарий от beastie

Есть такие маргиналы, как я например, у которых может и не быть stdlib с собой.

Dark_SavanT ★★★★★
()
Ответ на: комментарий от anonymous

Оригинальный способ считать количество символов. Я вместо этого взял через wolfram функцию, обратную к 2^((x-1)*4)

sambist ★★
() автор топика
Ответ на: комментарий от Eddy_Em

Почему машины, у которых vm.overcommit_memory=2 стали необычными? А если завтра в glibc перепишут malloc() и сделают, что он вызывает mmap с флагом MAP_POPULATE?

Исключая проверку результата malloc() мы получаем говнокод, потому что в необычном случае он будет падать с Segfault'ом, без сообщений о нехватки памяти или записи в логах от OOM-killer'а.

mky ★★★★★
()
Ответ на: комментарий от Eddy_Em

Например этот код выдаёт на моём 32-битном линуксе с 2-мя гигами оперативной памяти "(nil)". Запущен от рута без ulimit-ов.

#include <stdio.h>
#include <stdlib.h>
int main(void) {
      void *mem = malloc(4000000000u);
      printf("%p\n", mem);
      return 0;
}
Legioner ★★★★★
()
Ответ на: комментарий от anonymous
$ diff main.c.old main.c.new 
13c13
< char* intToHex(uint32_t value, uint32_t up, uint32_t pre, uint8_t msize)
---
> char* intToHex(uint32_t value, uint32_t up, uint32_t pre, int8_t msize)
28c28
<     ptr = result+2+n;
---
>     ptr = result+2;
30,31c30
<     result = malloc(sizeof(value)*2 + 1);
<     ptr = result+n;
---
>     ptr = result = malloc(sizeof(value)*2 + 1);
34c33
<   ptr[1] = 0;
---
>   ptr[n] = 0;
36,43c35,42
<     case 7: *ptr-- = hexdigit[value&0xf]; value>>=4;
<     case 6: *ptr-- = hexdigit[value&0xf]; value>>=4;
<     case 5: *ptr-- = hexdigit[value&0xf]; value>>=4;
<     case 4: *ptr-- = hexdigit[value&0xf]; value>>=4;
<     case 3: *ptr-- = hexdigit[value&0xf]; value>>=4;
<     case 2: *ptr-- = hexdigit[value&0xf]; value>>=4;
<     case 1: *ptr-- = hexdigit[value&0xf]; value>>=4;
<     case 0: *ptr-- = hexdigit[value    ];
---
>     case 7: ptr[7] = hexdigit[value&0xf]; value>>=4;
>     case 6: ptr[6] = hexdigit[value&0xf]; value>>=4;
>     case 5: ptr[5] = hexdigit[value&0xf]; value>>=4;
>     case 4: ptr[4] = hexdigit[value&0xf]; value>>=4;
>     case 3: ptr[3] = hexdigit[value&0xf]; value>>=4;
>     case 2: ptr[2] = hexdigit[value&0xf]; value>>=4;
>     case 1: ptr[1] = hexdigit[value&0xf]; value>>=4;
>     case 0: ptr[0] = hexdigit[value    ];
anonymous
()
Ответ на: комментарий от anonymous

Дай угадаю, результат close() тоже не проверяешь?

и что полезного с этим результатом потом можно сделать?

Harald ★★★★★
()
Ответ на: комментарий от Harald

Погугли, пустоголовый мишка кала!

anonymous
()
Ответ на: комментарий от Harald

и что полезного с этим результатом потом можно сделать?

Написать в лог

Gvidon ★★★★
()
Ответ на: комментарий от Eddy_Em

Если функция МОЖЕТ вернуть ошибку то программист ДОЛЖЕН ее обработать. Все кто с этим не согласен пишут анекдоты на C.

$ cat test.cpp 
#include <stdio.h>
#include <stdlib.h>

int main()
{
        void *p = malloc(((size_t)-1));
        if (p == NULL)
        {
                printf("p == NULL\n");
        }

        return 0;
}
$ g++ test.cpp -o test
$ ./test 
p == NULL
$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 31286
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 31286
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
quest ★★★★
()
Ответ на: комментарий от Eddy_Em
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
        void *ptr;

        if (!malloc(34359738368lu)) {
                fprintf(stderr, "ENOMEM!!!\n");
                exit(0);
        }

        return 1;
}
rymis ★★
()
Ответ на: комментарий от Sorcerer

Искусственный бред. Равно как и попытка выделить больше пары сот мегабайт оперативы (такие объемищи бывают нужны крайне редко — скажем, БПФ на огроменных изображениях делать).

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Знал бы ты какое говно линукс внутри местами. Так что тут песочница полная говна, но оно мелкое и сушёное, оттого похоже на песок.

И кстати да, uclinux на coldfire или blackfin вполне тебе может выдать NULL в ответ на malloc.

Dark_SavanT ★★★★★
()
Последнее исправление: Dark_SavanT (всего исправлений: 1)
Ответ на: комментарий от Dark_SavanT

Так что тут песочница полная говна, но оно мелкое и сушёное, оттого похоже на песок.

А у соседей вообще: либо асенизаторскую машину в песочницу опустошили, либо маньяки всю песочницу самотыками истыкали, либо песок скоммуниздили, либо песок нужно наперстком с соседней речки (которая в десяти километрах) перетаскать.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Искусственный бред.

А ты разве не знал, что это суть лора. Когда обезьяне ответить нечего в ход идут аргументы из этого разряда.

Равно как и попытка выделить больше пары сот мегабайт оперативы (такие объемищи бывают нужны крайне редко — скажем, БПФ на огроменных изображениях делать).

Суть даже не в этом - суть в том, что кусков больше пары мегабайт в юзкейсе хипа просто не бывает. Всё это отдельные, единичные аллокации, которые нормальные пацаны, да и сами аллокаторы не хранят в «хипе».

Нормальные пацаны для этого юзают mmap() и их код не упадёт на середине обработки изображения. А код обезьяны с маллоком отвалится, причем возможно даже со всей системой и ведром.

Проверить достаточно просто - берём любую смотрелку/обрабатывалку изображений - открываем файлец на объём в районе оперативки и смотрим как это говно падает. Нормальный же код скажет «не хвает памяти», отвалившись на префаулте в кернелспейсе и просто вернул ошибку в mmap().

Такая же история с текстовыми редакторами, да и со всем. Ещё ниразу я не видел программу, которая бы мне вернула «нету памяти», а не сдохла бы в муках как кусок говна.

А всё почему? Патамучто обезьяна вместо того, чтобы писать нормальный код, разобравшись в матчасти - проверяет на NULL. Проще же юзать бесполезность не дающую ничего, чем думать. Проще поверить в живительную силу проверки возврата маллока, и что оно не упадёт. И похрен что всё падает, важно же проверить, а не чтобы оно не падало.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.