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)
   while (conv.u != 0)
    {
        result[pos++] = hexdigit[sign(up)][conv.u & 0xF];
        conv.u >>= 4;
    }

sign(up) можно каждый раз не вызывать (впрочем, тут компилятор может догадаться).

yoghurt ★★★★★
()
Последнее исправление: yoghurt (всего исправлений: 1)

что вы понимаете под словом оптимизация?

anonymous
()

Вот, кстати, царь правильно говорил, что нет смысла проверять результат malloc: он никогда не вернет NULL!

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

Сделал так, спасибо:

...
    int32_t  upsgn = SmlSgn(up);
...

UPD: еще добавил:

if (pre)
{
    result[0] = '0';
    result[1] = 'x';
    pos = 2;
}
Чтобы не дергать цикл в strcpy.

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

Если не дергать маллок внутри - нет гарантии, что сверху выдадут достаточное количество памяти.

sambist ★★
() автор топика

Зачем тебе массив, если быстрей будет считаться

conv.u + 'a' - 10

?

И вообще, можно еще проще сделать, наподобие:

void printInt(uint8_t *val, int8_t len){
        P("0x");
        void putc(uint8_t c){
            if(c < 10)
                USB_Send_Data(c + '0');
            else
                USB_Send_Data(c + 'a' - 10);
        }
        while(--len >= 0){
            putc(val[len] >> 4);
            putc(val[len] & 0x0f);
        }
        USB_Send_Data(' ');
}

Eddy_Em ☆☆☆☆☆
()

Аноним несет пургу: ENOMEM никогда не возникнет. Не бывает такого в линуксе. Разве что если ты oomkiller отключишь совсем.

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

conv.u + 'a' - 10

Как вариант, наверное таки да. Зато масив красивше

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

Я и выделяю сколько мне надо. Функа для либы, в т.ч. эта будет торчать наружу из либы, так что сколько в нее запихнут - вопрос не ко мне. А так - очередная защита от дурака.

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

Между прочим, это — самый обычный gcc для ARM. И что здесь странного? В С вложенные функции давным-давно можно использовать.

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

вопрос не ко мне

Ну предел-то есть? Как MAX_PATH, слыхал про такое? А вот аллоцировать примитивный объект внутри функции - это огромный минус в дизайне. Сфига ли в стандартной либе st*cpy указывается аккумулятор, не задумывался? А почему? А потому что такое:

obj = alloc_obj();
do_op (obj);
free_obj(obj);

более явно, чем

obj = alloc_and_do_obj();
free_obj(obj);

Какбе неочевидно, что free там нужен. К тому же возвращать указатель тут - явный бред, можно вернуть код ошибки, например

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

У меня регулярно 100% памяти занято случается, и до того как прийдёт oom-killer можно минут 5 покурить ещё, или заниматься делами и не замечать

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

Писал не тебе - почитай.

А потом из-за тебя ошибки в сслях:

Я уже где-то показывал.

enum {KB = 1024, MB = KB * 1024, GB = MB * 1024};

int main(void) {
  void * a = malloc(GB * 8ul);
  if(!a) perror("jopa a");
  void * b = malloc(GB * 8ul);
  if(!b) perror("jopa b");
  memset(a, 0, GB * 8ul);//память выделяется вот тут. И падать будет тут.
  memset(b, 0, GB * 8ul);//и вот тут. И тут тоже будет падать.
}

Этот кусок кода падает у меня, ибо свободной памяти 13гигов. И маллок вернёт «еномем» только если ты попросишь больше 13гигов. Если ты попросишь 10005000 раз по 12гигов - ничего не будет. А вот когда ты будешь писать в эту память - тебя убьёт ООМ-киллер.

The malloc() and calloc() functions return a pointer to the allocated memory if successful; otherwise a NULL pointer is returned and errno is set to ENOMEM.

Маллок не может вернуть ENOMEM, ибо он не работает в мемори. Вернуть что-то маллок может лишь когда ты запросишь кусок больше рамы, если врублен оверкоммит. На аллокации меньше пейджсайза проверять маллок смысла нет - они никогда не вернул нал, даже если у тебя 0свободной памяти.

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

Это всё детали конкретной реализации (линукса) и настроек, которые в будущем могут поменяться. Если стандарт говорит, что может вернуть NULL - считаем, что когда-нибудь вернёт

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

Неправильно.

Вот:

char * intToHex(uint8_t *value, size_t L, char up){ uint8_t ch = up ? 'A' : 'a'; inline char *nxt(uint8_t x){ if(x > 10) return (x + '0'); else return (x + ch - 10); } ... char *ret = MALLOC(L), *ptr = ret; for(i = L-1; i >= 0; i--){ *ptr++ = nxt(value >> 4); *ptr++ = nxt(value & 0x0f); } char *X = strdup(ret); FREE(ret); return X; }

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

Ага, процентом единым. Pure c.

На линуксе работает 70-95% полезного кода в мире.

Это поведение не линукса, а любой нормальной ОС, даже убогой маздайке. Это поведение даже не ОС, а самой модели памяти.

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

Хитрец — не хитрец, но городить костыли и переизобретать вылизанный поколениями код — жуткий моветон.

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

А вот и нет: моветон — использовать glibc в микроконтроллерах. Но у ТСа, судя по malloc, никакие не микроконтроллеры. Он просто дурью мается!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em
char * intToHex(uint8_t *value, size_t L, char up)
{
   uint8_t ch = up ? 'A' : 'a';

   inline char *nxt(uint8_t x)
   {
      if(x > 10) return (x + '0');
         else 
            return (x + ch - 10);
   } 

   ... 
   char *ret = MALLOC(L), *ptr = ret; 
   for(i = L-1; i >= 0; i--)
   {
      *ptr++ = nxt(value >> 4);
      *ptr++ = nxt(value & 0x0f);
   }
   char *X = strdup(ret); 
   FREE(ret); 
   return X; 
}
sambist ★★
() автор топика
Ответ на: комментарий от beastie

Тут, наверное, будет много удаленных весьма полезных комментов, да?

А зря, рацзерно в них есть

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

Напиши, пожалуйста, простой кусок кода, чтобы воспроизвести на обычной (подчеркиваю, обычной, а не ограниченной всякими ulimit и sysctl) машине случай, когда alloc вернет NULL.

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

Послушай анонимуса.

Вся офигенность сишечки в том, что можно делать низкоуровневый код достаточно кроссплатформенным.

И если ты завязываешься на конкретной платформе без серьёзной причины, то ты не очень хороший программист :(

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

Пасибки. А то я тут мало того, что уже год никак не накоплю на 1 звезду (чтобы не было позорной паузы в 30 секунд и чтобы редактировать можно было), так еще и сижу на чертовом 3G, который тупит, как собака!

mono, что ж у вас такой интернет-то дерьмовый? Знал бы, брал бы MTS...

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

Ты явно забыл упомянуть, где так глибц

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

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

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

Замени glibc на любую другую библиотеку. Нельзя в микроконтроллерах библиотеки.

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

У меня всего 2ГБ на домашнем компьютере! Не покупать же мне новый компьютер лишь из-за того, что некоторые рукозадые быдлокодеры нормальный софт писать не умеют?

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

Это всё детали конкретной реализации

Какого нахрен линукса. Это детали модели памяти, которая сейчас везде. Кроме низших аврок и прочего 8-ми битного говна.

Тот код, который пишет сишник работает либо с этой моделью памяти, либо там нет ни маллока, ни прочего говна, типа хипа в твоём рантайме.

настроек

Не могут, никто в здравом уме не врубит жесткий оверкоммит. Его могут максимум вырубить, тогда твой маллок уже никогда нал не вернёт.

которые в будущем могут поменяться

Не могут.

Если стандарт говорит, что может вернуть NULL - считаем, что когда-нибудь вернёт

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

Маллок не гарантирует выделение памяти. Вообще никак.

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

Ну так ССЗБ. Ты ещё подревнее комп найди и скажи, что только Win98 - Ъ, а остальное - жирное говно

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

Пишу с 2Гб на встроенном интеле.

P.S. У меня в коде бага - не тот порядок байт. Например вместо 1024 -> 400 будет 1024 -> 004. Как поправить?

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