cool.2k7
cool.2k7

Reputation: 21

_int64 bit field

I need to use a 6-byte (48-bit) bitfield in a structure that I can use as unsigned integer for comparison etc. Something along the following:

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

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

But somehow on 64-bit Windows, sizeof this struct always returns 8 bytes instead of 6 bytes. Any pointers are appreciated?

Upvotes: 1

Views: 4164

Answers (3)

randomness2077
randomness2077

Reputation: 1139

I did some google search. Found out you might be able to use __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

But, as you said you are using Windows, which might be different.

I could be wrong, if so just point it out.

BTW, I still do not know what is the best solution to this question. Using struct makes thing a little awkward (you need call a._m instead of a, could we get round with it?) But at least it seems safer than just using uint64_t.

Upvotes: -1

Pavan Manjunath
Pavan Manjunath

Reputation: 28525

You have used _int64 and hence sizeof returns 8. Its like you've decided to use up 48 bits out of the available 64 bits. Even if we declare something like this-

struct my_struct {
  _int64 var1:1;
} s;

Still sizeof would say 8. In short, allocation of bitfields would take place according to the type of the bitfield. In this case its _int64 and hence 8 bytes allocation.

Upvotes: 3

Lindydancer
Lindydancer

Reputation: 26094

Unfortunately, a bit filed have the size of the underlying type, in this case an _int64 is 8 bytes.

As there is no six byte integers in any compiler that I know of, you would have to find a better way. One is to use one 16 and one 32 bit value (or three 16 bit values) and write your own comparison function.

For example:

struct my_struct
{
  uint16_t high;
  uint32_t low 
} s;

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

As a bonus you don't need #pragma pack, which brings a lot of other problems.

Upvotes: 2

Related Questions