I'm trying to store 3 integers (ie 21 bits each) in one long int with these macros:
typedef long int Triple;
#define TR_A(o) ((int)((o & 0x7FFFFC0000000000) >> 42))
#define TR_B(o) ((int)((o & 0x000003FFFFE00000) >> 21))
#define TR_C(o) ((int)(o & 0x00000000001FFFFF))
#define MK_TR(a,b,c) ((long int)((a<<42) & (b<<21) & c))
So the idea is that o is 64 bits, and a,b,c are 32 each. When stored inside o they are 21 bits, and the 64 bits are empty bit, a, b, and then c.
I get a bunch of these errors:
warning: left shift count >= width of type [-Wshift-count-overflow]
#define MK_TR(a,b,c) ((long int)((a<<42) & (b<<21) & c))
^
Is it possible to add something to TR_A/TR_B/TR_C that specifies that o is long?
Any better way to do this?
I want to be able to return these as simple values, not pointers. Using Linux on PC.
You can specify that an integer literal (constant) should be interpreted as a long int by adding the L suffix (or a lowercase l - but this looks too much like a 1 for my comfort). Similarly, for a long long int, add the LL suffix.
In the case of your macros, you will also need to explicitly cast the arguments, a, b and c to the appropriate (long or long long) type.
However, rather than relying on a particular compiler to implement long int as a 64-bit type (many compilers do not, and use 32-bits for both int and long int, and require long long int for a 64-bit type), you should use the bit-width specific types defined in the <stdint.h> header file.
Thus, the following code should be warning-free and portable:
#include <stdint.h>
typedef int64_t Triple;
#define TR_A(o) ((int32_t)(((int64_t)(o) & 0x7FFFFC0000000000LL) >> 42))
#define TR_B(o) ((int32_t)(((int64_t)(o) & 0x000003FFFFE00000LL) >> 21))
#define TR_C(o) ((int32_t)((int64_t)(o) & 0x00000000001FFFFFLL))
// EDIT/NOTE: I have changed the bitwise & operations to | in the macro below,
// as this is probably what you actually want (otherwise it will give 0 always)!
#define MK_TR(a,b,c) ((int64_t)(((int64_t)(a) << 42) | ((int64_t)(b) << 21) | (int64_t)(c)))
Also, it is very good practice to always include your macro arguments in parentheses (such as (c) in the last line, above). Without this, a call to your macro with an expression as an argument can give you unexpected results, which can be difficult to track down. This would be a case in point:
int a = 1, b = 2, c = 3;
Triple test = MK_TR(a + 1, b + 1, c + 1); // Unexpected(?) result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With