LINUX.ORG.RU

Записать в 11-битовое поле два десятичных числа.

 


0

1

Что то я туплю, как обычно. Задача такае - есть поле из 11 бит. В первый бит всегда пишем 1. Остальные 10 бит деляться на два поля по пять бит - в них могут храниться числа с 0 по 31(11111). Например эти 11 бит храняться в short. Мне передают два десятичных числа, например 5 и 2, надо чтобы в этом short получилось 10010100010 (1186 в десятичном виде).

Подскажите как это соорудить на Си.

Битовый сдвиг?

bj
()
short res = (1 << 10) | ((a & 31) << 5) | (b & 31);

Можно ещё заюзать union, struct и битовые поля:

union {
    struct {
        unsigned b : 5;
        unsigned a : 5;
        unsigned h : 1;
    } in;
    short out;
} u;
u.out = 0;
u.in.b = b;
u.in.a = a;
u.in.h = 1;
short res = u.out;

Возможно, второе не взлетит на big endian.

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

да знаю про << |, говорю же - туплю. Если кому не влом, можно пример с кодом.

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

The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined.

Плюс выравнивания и паддинги.

Нда, а мне почему-то казалось, что такое применение переносимо...

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

А ещё если бы это был C++, а не C, то было бы ещё и неопределённое поведение там, где мы сначала записываем в u.in, а потом вычитываем u.out.

In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.

А в C это работает:

If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type punning’’).

Большинство компиляторов ведут себя так же и в C++, однако не компилятор от Sun, например.

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

Подскажите как это соорудить на Си.

А банальное res = 1024 + n1 * 32 + n2 это уже не С?

sdio ★★★★★
()
Ответ на: комментарий от gentoo_root
  short res = (union {
    uint16_t out;
    struct {
      uint16_t b: 5;
      uint16_t a: 5;
      uint16_t h: 1;
      uint16_t _: 5;
    } in;
  }){
    .in = {b,a,1,0}
  }.out;
anonymous
()
Ответ на: комментарий от gentoo_root

А ещё если бы это был C++, а не C

Кстати да, коипилиться этот кусок Си будет в g++

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

Возможно, второе не взлетит на big endian

С этой чертовой архитектурой вообще жесть! Я постоянно, хоть и перепроверяю, нарываюсь на косяки при написании кода под ARM. Вечно забываю, что там черезжопный порядок байт!

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

А банальное res = 1024 + n1 * 32 + n2 это уже не С?

Поясни логику, а то я по пьяни не соображу... Битывые варианты мне понятны, а твой самый клёвый не пойму.. модет утром пойму)))

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

А что там в ARMe не так с порядком байт?

Я слышал, что армы могут работать в любом порядке байт: и в big-endian, и в little-endian. У меня Raspberry Pi работает, естественно, в little-endian, потому что она может в нём работать и он лучше.

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

Гугли разницу между big-endian и little-endian. А в остальном все ОК, тупо с бинарными данными надо быть осторожным.

Eddy_Em ☆☆☆☆☆
()

unC0Rr
Кто предлагает сдвинуть на 10 бит- т.е. все в этом треде - упоролись.

Это ты упоролся! Как ты запишешь, скажем, в восьмибитную переменную два четырехбитных значения, не сдвигая второе на 4 бита?

НИКАК¡!¡

Без битового сдвига ты никак не обойдешься.

Eddy_Em ☆☆☆☆☆
()

Да подожди ты! Тут строки склеить не могут с прошлого года, а ты со своими битами лезешь.

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

Строки склеили буквально на третьей-четвертой странице. Потом еще страниц пять велосипедов навыдумывали, а потом начался обычный срач.

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

Да я, собствеено, не про битовый сдвиг, а про сдвиг конкретно на 10. Поскольку у автора нумерация бит непонятная, но посмотрел пример и понял, что сам упоролся.

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

Да подожди ты! Тут строки склеить не могут с прошлого года, а ты со своими битами лезешь.

Тот тред мне весьма доставил))

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

:(

#include<stdio.h>
short sft5add(x,y)
        short x,y;{
                return (x<<5)+(y&31);
}

short eleven_bit_1ab(a,b)
        short a,b;{
                short c=1;
                c=sft5add(c,a);
                c=sft5add(c,b);
                return c;
}
int main(){
         return fprintf(stderr,"%d\n",eleven_bits_1ab(5,2));
}

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

Видимо потому что uint8_t есть только на определённых платформах или в дровах некоторых. Даже Qt чаще используют int, short и т.п. хотя есть qint8, qint16

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

да тут ничего уже не поделаешь: 6.2.5 Types

4. There are five standard signed integer types, designated as signed char, short int, int, long int, and long long int. (These and other types may be designated in several additional ways, as described in 6.7.2.) There may also be implementation-defined extended signed integer types. 38) The standard and extended signed integer types are collectively called signed integer types. 39)

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