Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bit masks and long-long

Tags:

c++

I have a masking procedure (which creates an all-ones bit mask for the bottom half for a given size):

template<class T>
T bottom_half() {
    T halfway = ((sizeof(T) * 8) / 2);
    T mask = (1 << halfway) - 1;

    return mask;
}

which works fine if I call bottom_half<int>() or long or char. But for some reason when I run it with long long, halfway is correctly set to 32, but mask is 0. Why would that be?

like image 251
sircodesalot Avatar asked Sep 17 '13 18:09

sircodesalot


People also ask

What is the purpose of a bit mask?

Bit masks are used to access specific bits in a byte of data. This is often useful as a method of iteration, for example when sending a byte of data serially out a single pin. In this example the pin needs to change its state from high to low for each bit in the byte to be transmitted.

What do you mean by bit masking?

Masking is the act of applying a mask to a value. This is accomplished by doing: Bitwise ANDing in order to extract a subset of the bits in the value. Bitwise ORing in order to set a subset of the bits in the value. Bitwise XORing in order to toggle a subset of the bits in the value.

What is bit masking in C++?

Bitmask also known as mask is a sequence of N -bits that encode the subset of our collection. The element of the mask can be either set or not set (i.e. 0 or 1). This denotes the availability of the chosen element in the bitmask. For example, an element i is available in the subset if the ith bit of mask is set.


2 Answers

The left shift is shifting 1, which is int by default and probably 32 bits on your machine. When you shift 1<<32, the result is undefined, which means it is not predictable anymore, as it could be anything.

On some processors, 1<<32 might result in shifting the bit off the high end of the integer and resulting in 0. On other processors, the 32 shift is modulo the register size, so effective it is a zero shift, and the result is 1. In any case, it is undefined.

(See What's bad about shifting a 32-bit variable 32 bits? for a discussion on this).

Note also that sizeof returns units char or "bytes" (these are defined to be the same in C, sizeof(char) == 1 always), but C does not guarantee that a byte is 8 bits. There is standard macro CHAR_BIT to get the bit size of a char.

Try this

#include <limits.h>

template<class T>
T bottom_half() {
    T halfway = ((sizeof(T) * CHAR_BIT) / 2);
    T mask = ((T)1 << halfway) - 1;

    return mask;
}
like image 64
Mark Lakata Avatar answered Oct 28 '22 21:10

Mark Lakata


The expression 1 << x has type int. Left-shifting a signed type such that the value exceeds the maximum representable value has undefined behavior. Use T(1) << x instead.

like image 43
Dietmar Kühl Avatar answered Oct 28 '22 20:10

Dietmar Kühl