8

gcc 4.4 seems to be the first version when they added int128_t. I need to use bit shifting and I have run out of room for some bit fields.

Edit: It might be because I'm on a 32-bit computer, there's no way to have it for a 32-bit computer (Intel Atom), is there? I wouldn't care if it generated tricky slow machine code if I would work as expected with bit shifting.

phuclv
  • 37,963
  • 15
  • 156
  • 475
Roman A. Taycher
  • 18,619
  • 19
  • 86
  • 141
  • This is a special case of [Is there a 128 bit integer in gcc?](https://stackoverflow.com/q/16088282) which does cover the fact that GCC4.1 and later have `__uint128_t`, but only on 64-bit targets. That question *doesn't* attempt to provide workarounds, other than C23 `_BitInt(128)` supported by clang even on 32-bit machines, so maybe not a duplicate. – Peter Cordes May 13 '22 at 17:52

4 Answers4

9

I'm pretty sure that __int128_t is available on earlier versions of gcc. Just checked on 4.2.1 and FreeBSD and sizeof(__int128_t) gives 16.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
janm
  • 17,976
  • 1
  • 43
  • 61
  • This doesn't seem to work with the earlier gcc 4.1.2 (e.g. as in RHEL 5) – Joseph Quinsey Aug 20 '13 at 18:49
  • 1
    @JosephQuinsey It [does work with gcc 4.1.2](https://godbolt.org/z/ybSSRn) – phuclv Aug 21 '18 at 04:58
  • unfortunately this won't work for the OP since he's using a 32-bit OS. GCC only supports types twice as wide as the register size, thus `__int128_t` won't be available if compiled with `-m32` – phuclv Jan 06 '19 at 06:40
4

You could also use a library. This would have the advantage that it is portable (regarding platform and compiler) and you could easily switch to even bigger datatype. One I could recommend is gmp (even if its intention is not to handle bitwidth x, but variable as big as you want).

flolo
  • 15,148
  • 4
  • 32
  • 57
2

Bit shifting is very easy in any arbitrary number of bits. Just remember to shift the overflowed bits to the next limb. That's all

typedef struct {
   int64_t high;
   uint64_t low;
} int128_t;


int128_t shift_left(int128_t v, unsigned shiftcount)
{
   int128_t result;
   result.high = (v.high << shiftcount) | (v.low >> (64 - shiftcount));
   result.low  =  v.low  << shiftcount;
   return result;
}

Similar for shift right

int128_t shift_right(int128_t v, unsigned shiftcount)
{
   int128_t result;
   result.low  = (v.low  >> shiftcount) | (v.high << (64 - shiftcount));
   result.high =  v.high >> shiftcount;
   return result;
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
1

You could use two 64-bit ints, but then you need to keep track of the bits moving between.

Andrew Cooper
  • 32,176
  • 5
  • 81
  • 116