C - BitArray - set one bit uint64_t

I am currently working on a project in which I need bit sets. I am using uint64_t array for bit set.

My current problem is that whenever I want to set or check a bit, I need to perform the following operation:

 uint64_t index = 42; bArr[index/64] |= (((uint64_t)1)<<(index%64)); 

I can rewrite the division modulo with some smart and bitwise operations, but listing 1 bothers me. I need this tide, since otherwise 1 treated as a 32-bit unit. As you can see from this example, you get the wrong output without casting:

 uint64_t bArr[4]; // 256 bits bArr[0] = bArr[1] = bArr[2] = bArr[3] = 0; // Set to 0 uint64_t i = 255; bArr[i/64] = (bArr[i/64] | (((uint64_t)1)<<(i%64))); uint32_t i2; for (i2 = 0; i2 < 256; i2++) { if ((bArr[i2/64] & (((uint64_t)1)<<(i2%64))) != 0) { printf("bArray[%" PRIu32 "] = 1\n", i2); } } 

Can I get around this toss in a smart way? I thought that performance probably suffers from a cast on every read / write ...

+6
source share
4 answers

The result type of the operator << is the type of the left operand (after whole promotions), so you need to use the correct type: 1 is of type int , but you need to enter uint64_t .

You can use either:

 (uint64_t) 1 

or

 UINT64_C(1) /* you have to include <stdint.h> */ 

or

 1ULL 

(for the latter, assuming unsigned long long is 64-bit on your system, which is very likely).

But they are all equivalent: all these expressions are integer constant expressions, and their value is computed at compile time, and not at run time.

+4
source

Actuation alone does not affect performance. This is a time compilation that tells the compiler the type of expression.

In this case, they are integers and expressions, so there should be no performance impact.

+3
source

C offers macros for this, which will extend the integer constant to type int_leastN_t .

 INTN_C(value) UINTN_C(value) 

Example

 #include <stdint.h>. bArr[index/64] |= UINT64_C(1) << (index%64); 

In general, it is better to avoid casting. Sometimes casting unexpectedly makes the expression narrower than you might expect.


You can use UINT64_C types: uint_least_64_t/int_least_64_t (C99). int64_t/uint64_t are optional.

+3
source

If I understand you correctly, you need a literal 1 with a length of at least 64 bits. You can get this without any throws by writing 1ull , not just 1 . This creates an unsigned long long literal with a value of 1. However, the type does not guarantee that it will not be longer than 64-bit, therefore, if you rely on the fact that it exactly matches 64-bits, you may need to throw.

+1
source

All Articles