Извлечение двух целых чисел со знаком из одного заданного целого числа?

У меня есть следующая структура:

struct
{
int a:4;
int b:7;
int c:21;
} example;

Я хотел бы объединить a и b, чтобы сформировать целое число d в C ++. Например, я хотел бы, чтобы значения битов a были слева от значений битов b, чтобы сформировать целое число d. Как это реализовано в C ++?

Пример:

а = 1001

b = 1010101

Я хотел бы int d = 10011010101 ххххххххххххххххххх

где x может быть 21 битом, который ранее принадлежал d. Я хотел бы, чтобы значения a и b были помещены в позиции битов 0-3 и 4-10 соответственно, поскольку a занимает первые 4 бита, а b занимает следующие 7 битов в структуре «example».

Часть, в которой я запутался, заключается в том, что переменная a и переменная b имеют бит знака в старшем значащем бите. Влияет ли это на результат? Все ли биты в переменной a и переменной b используются в конечном результате для целого числа d? Будет ли целое число d выглядеть как конкатенация битов переменной а и битов переменной b?

Спасибо

0

Решение

Обратите внимание, что ли int битовое поле со знаком или без знака определяется реализацией. Стандарт C ++ говорит об этом, и стандарт C достигает одного и того же результата с другой формулировкой:

ISO / IEC 14882: 2011 — C ++

§7.1.6.2 Спецификаторы простого типа

¶3 … [Примечание: это определяется реализацией, являются ли объекты char Тип и некоторые битовые поля (9.6)
представлены как подписанные или неподписанные количества. signed Спецификатор силы char объекты и битовые поля, которые будут
подписан; это избыточно в других контекстах. —Конечная записка]

§9.6 Битовые поля

¶3 … Битовое поле должно иметь целочисленный тип или тип нумерации (3.9.1). это
определяется ли реализация простым (ни явно подписанным, ни неподписанным) char, short, int, long,
или же long long битовое поле подписано или не подписано.

ISO / IEC 9899: 2011 — C

§6.7.2.1 Структура и спецификаторы объединения

¶10 Битовое поле интерпретируется как имеющее целочисленный тип со знаком или без знака, состоящий из указанного количества битов.125)

125) Как указано в 6.7.2 выше, если фактический используемый спецификатор типа является int или typedef-name, определенным как int, то это определяется реализацией, является ли битовое поле подписанным или беззнаковым.

§6.7.2 Спецификаторы типа

¶5 … для битовых полей, определяется ли реализация спецификатором int обозначает тот же тип, что и signed int или того же типа, что и unsigned int,

Контекст §6.7.2 показывает, что int можно сочетать с short, long и т. д., и правило будет применяться; C ++ уточняет это немного более четко. Подпись равнины char конечно, уже определяется реализацией.


Битовые поля без знака

Если тип битовых полей не имеет знака, то выражение довольно простое:

int d = (example.a << 7) | example.b;

Подписанные битовые поля

Если значения подписаны, то вам нужно выполнить основную интерпретацию, решив, какое значение должно быть, если example.a отрицательно и example.b положительно, или наоборот. В некоторой степени проблема возникает, даже если значения оба являются отрицательными или оба положительными.

предполагать example.a = 7; а также example.b = 12; — какой должна быть стоимость d? Возможно, применимо то же выражение, но вы можете утверждать, что было бы лучше сместить на 1 место меньше:

assert(example.a >= 0 && example.b >= 0);
int d = (example.a << 6) | example.b;      // Alternative interpretation

Остальные дела оставлены на ваше усмотрение; это зависит от интерпретации, которую вы хотите поместить в ценности. Например:

int d = ((example.a & 0x0F) << 7) | (example.b & 0x7F);

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


Модифицированный вопрос

example.a = 1001     // binary

example.b = 1010101  // binary

d = 10011010101 xxxxxxxxxxxxxxxxxxxxx

где x может быть 21 битом, который ранее принадлежал d.

Чтобы это работало, тогда вам нужно:

  d = (d & 0x001FFFFF) | ((((example.a & 0x0F) << 7) | (example.b & 0x7F)) << 21);

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

союз

Тем не менее, с этой пересмотренной спецификацией, вы вполне можете испытать искушение взглянуть на union такие как:

union u
{
struct
{
int a:4;
int b:7;
int c:21;
} y;
int x;
} example;

Однако расположение битов в битовых полях с битами в int x; не указан (это могут быть старшие значащие биты в первую очередь или младшие значащие биты в первую очередь), и всегда есть бормотание о том, «если вы обращаетесь к значению в объединении, которое не было назначено последнему, вы вызываете неопределенное поведение». Таким образом, вы имеете дело с несколькими аспектами битового поля, определяемыми платформой. Фактически, этот тип головоломки обычно означает, что битовые поля тесно связаны с одним конкретным типом машины (ЦП), компилятором и операционной системой. Они очень, очень непереносимы на том уровне детализации, который вам нужен.

2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector