LINUX.ORG.RU

Конвертирование нестандартной длинны int в обычный.


0

1

C++ В процессе реализации столкнулся с ситуацией что в разных местах приходится использовать инты разной длинны. Т.е. встречаются 2,3,4,5 байтные инты. В то время как прочесть 2,4 байтные не есть проблема (КО как бы подсказывает), то с нестандартными длиннами все не так :) Как правило сами значения находятся в целостном потоке данных. На текущий момент я решаю это банальным копирование побайтовым в переменную нужного типа, что то вроде того:

uint32_t var;
uint8_t *p = &var;
p[0] = data[offset];
p[1] = data[offset+1];
p[2] = data[offset+2];
p[3] = 0x00;
Существует ли альтернативный способ считывать нестандартной длинны данные/значения ?

★★★★★

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

Нет. Но лучше делать так, как написал анонимус. В его способе endianness задается только входным потоком.

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

в моём случае код для чтения из потока LE в архитектурах и LE, и BE. в твоём случае будет работать поток LE только на LE-архитектурах (и соответственно BE-поток на BE-архитектурах)

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

Да, спасибо, это я понимаю, тот пример просто для иллюстрации вопроса :)
Кстати в моем примере BE не прочитается верно :)
В моем случае исходный поток BE :)

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

в ограниченом числе случаев может сработать и кастинг указателя, вроде такого var = ( *((uint32_t *)(data+offset)) ) &0xffffff, но тут кроме возможных граблей с endianess могут добавиться грабли с data alignment, например, на arm.

anonymous
()
Ответ на: комментарий от anonymous
 var = data[offset] + (data[offset+1] << 8) + (data[offset+2] << 16) 

я надеюсь, анонимус понимает, что тут не int, а unsigned?

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

> Это где 5 байтные инты? O_O
бывают и 5, и 8, и 11.375-байтные инты

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

Я подозреваю, что ТС имеет ввиду просто целые числа(аналог - bignum), а не те, которые в компиляторе.

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

>> Хуже, чем сдвиг.

от задачи зависит...

С union { uint32_t i; char c[4]; } в массив c придется записывать байты в порядке, зависящем от endianness.

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

Во множестве бинарных протоколов :)
Очень часто экономят байты на целочисленных относительных значениях.

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

по макросу на каждую пару эндианес :) Просто было интересно существуют ли какието штатные средства :) Насколько я понял - нет :)

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

>в массив c придется записывать байты в порядке, зависящем от endianness.

безусловно. Но это иногда полезно - ведь если мы передаём данные на внешний порт, они и так зависят от порядка. Можно сделать так, что записав данные в union мы их сможем передать наружу, при этом передаваться они будут правильно независимо от endianess.

Кроме того, используя union мы можем быстро упаковать 8 пятибайтовых числа, в 5 восьмибайтовых (long long). Согласитесь, что двигать тут будет дольше, а 40битной памяти не бывает (что-бы записывать туда пятибайтовые числа). Потому паковать вам всё равно придётся.

Конечно, union оптимальны далеко не всегда, мало того, часто компилятор сам их начинает двигать. Зато они легкочитаемы.

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

Не читал топик? :)
Вопрос не в преобразовании БЕ-ЛЕ или наоброт вопрос в интерпретации произвольной длинны значений как инт штатными средствами:)

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