_int64-битное поле

Мне нужно использовать 6-байтовое (48-битное) битовое поле в структуре, которую я могу использовать как целое число без знака для сравнения и т. д. Что-то вроде следующего:

pack (1)
struct my_struct {
  _int64 var1:48;
} s;

if (s.var >= 0xaabbccddee) { // do something }

Но почему-то в 64-битной Windows sizeof эта структура всегда возвращает 8 байтов вместо 6 байтов. Любые указатели приветствуются?


person cool.2k7    schedule 06.03.2012    source источник
comment
Что произойдет, если вы используете тип, отличный от _int64, например int? Компилятор имеет право решать, должна ли структура быть выровнена по 4 или 8 байтам (а не по 2 байтам). Упаковка — это просто подсказка компилятору.   -  person Jonathan Leffler    schedule 06.03.2012


Ответы (3)


Вы использовали _int64 и, следовательно, sizeof возвращает 8. Это похоже на то, что вы решили использовать 48 бит из доступных 64 бит. Даже если мы объявим что-то вроде этого-

struct my_struct {
  _int64 var1:1;
} s;

Тем не менее sizeof будет означать 8. Короче говоря, распределение битовых полей будет происходить в соответствии с типом битового поля. В данном случае это _int64 и, следовательно, выделение 8 байт.

person Pavan Manjunath    schedule 06.03.2012
comment
Спасибо, Паван. Есть ли способ использовать 48-битный #, чтобы я мог выполнять основные операции с полем, такие как +, -, ›, ‹ и т. Д., Точно так же, как я делал бы это с _int64? - person cool.2k7; 06.03.2012
comment
Если вы видите это-msdn.microsoft.com/ en-us/library/aa261215(v=vs.60).aspx, вы также можете создать 64-битный тип битового поля целое число без знака и использовать его. Вы можете выполнять все основные операции, как обычно. Вам не нужно беспокоиться о неиспользуемых 16 битах! - person Pavan Manjunath; 06.03.2012
comment
Я понимаю эту часть, но мне нужна структура (или тип), которая использует только 48 бит, но семантически может использоваться так же, как _int64 для основных операций. ??? - person cool.2k7; 06.03.2012
comment
Могу ли я узнать, что является тем, что налагает такие строгие требования? Чтобы мы могли подумать об альтернативах? Что вас больше беспокоит? Скорость или простота использования? - person Pavan Manjunath; 06.03.2012
comment
Конечно. моя структура представляет пакет протокола, который имеет 48-битное поле и, следовательно, требует места. поле требует некоторых основных операций, таких как ›=, +, - и т. д., которые должны выполняться не медленнее, чем для обычного _int64, и, следовательно, требуется использовать _int64 для основных операций. Спасибо. - person cool.2k7; 06.03.2012
comment
также у меня есть существующая большая кодовая база, которая имеет то же поле, что и 32-битное, и теперь я хочу изменить это поле на 48-битное, не меняя остальную часть кода, выполняющего операции с этим полем. - person cool.2k7; 06.03.2012

К сожалению, битовое поле имеет размер базового типа, в данном случае _int64 составляет 8 байт.

Поскольку ни в одном известном мне компиляторе нет шестибайтовых целых чисел, вам придется найти лучший способ. Один из них — использовать одно 16-битное и одно 32-битное значение (или три 16-битных значения) и написать собственную функцию сравнения.

Например:

struct my_struct
{
  uint16_t high;
  uint32_t low 
} s;

if (   (s.high > 0xaa)
    || (   (s.high == 0xaa)
        && (s.low >= 0xbbccddee)))
{ ... do something ... }

В качестве бонуса вам не нужен #pragma pack, который приносит много других проблем.

person Lindydancer    schedule 06.03.2012
comment
Во многих системах эта структура будет состоять из 8 байтов с 2 байтами заполнения между high и low. - person Jonathan Leffler; 06.03.2012
comment
Благодарю за ваш ответ. Это именно то, чего я хочу избежать, чтобы выполнить множественное сравнение, когда я знаю, что _int64 можно сравнивать при сравнении. - person cool.2k7; 06.03.2012
comment
Ты прав. Однако, если вы используете массив из трех 16-битных значений, как я также предложил в ответе, все должно быть в порядке. Однако выражение сравнения будет несколько более сложным. - person Lindydancer; 06.03.2012

Я сделал поиск в Google. Узнал, что вы можете использовать __attribute__((packed)).

http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Type-Attributes.html

  24 typedef struct __uint48_t uint48_t;                                             
  25 struct __attribute__((packed)) __uint48_t {                                     
  26     uint64_t _m:48;                                                             
  27 };      

 29 void test()                                                                     
 30 {                                                                               
 31     uint48_t a;                                                                 
 32     a._m = 281474976710655;                                                     
 33     printf("%llu", a._m);                                     
 34     printf("%u", sizeof(a));                                                  
 35                                                                                 
 36     a._m = 281474976710656;                                                     
 37     printf("%llu", a._m);                                                     
 38 }                   

 main1.c: In function ‘test’:
 main1.c:36:2: warning: large integer implicitly truncated to unsigned type [-Woverflow]

 $ ./a.out 
 281474976710655
 6
 0

Но, как вы сказали, вы используете Windows, которая может отличаться.

Могу ошибаться, если так, то укажите на это.

Кстати, я до сих пор не знаю, что является лучшим решением этого вопроса. Использование struct делает ситуацию немного неудобной (вам нужно вызывать a._m вместо a, можем ли мы обойтись без этого?) Но, по крайней мере, это кажется более безопасным, чем просто использование uint64_t.

person randomness2077    schedule 08.11.2012
comment
packed определяет только возможность вставки заполнения между выровненными элементами. Это не позволяет членам стать несогласованными. Базовый тип битового поля — uint64_t, поэтому для него по-прежнему требуется выравнивание по 8 байтам. - person underscore_d; 05.01.2016
comment
обратите внимание, что результат sizeof должен быть напечатан с использованием %zu - person phuclv; 08.08.2019