Charles - 3 months ago 11

C Question

This is for a C89 project, in which

`LONG_IS_64BIT`

`long`

I have a number

`n`

`LONG_IS_64BIT`

At the moment the code has

`(1L<<n) - 1`

`long`

`n==63`

`n==31`

I suppose I could just test for

`n==31`

`n==63`

Answer

If you know the mathematical value of `(1L<<n)-1`

fits in `long`

, you can ensure you don't overflow by calculating the value minus one, and then adding one, rather than calculating the value plus one, and then subtracting one.

```
n == 0 ? 1 : ((1L<<n-1)-1<<1)+1
```

It's convoluted, requiring special casing to avoid left shift by a negative value if `n == 0`

, but at least it gets you the value you need.

Alternatively, you can use a right shift:

```
#ifdef LONG_IS_64BIT
0x7FFFFFFFFFFFFFFF>>(63-n)
#else
0x7FFFFFFF>>(31-n)
#endif
```

You can't use `LONG_MAX`

here if it could well be larger than you expect.

Realistically though, @melpomene's comment to use `unsigned long`

should be good enough. The platforms where it has the same amount of value bits as `long`

were already uncommon back when the standard was written. And if you already sort of assume `long`

will have exactly 32 or exactly 64 bits, you probably shouldn't worry about the more esoteric implementations.