What is CHAR_BIT? What is CHAR_BIT? c c

What is CHAR_BIT?


CHAR_BIT is the number of bits in char. These days, almost all architectures use 8 bits per byte but it is not the case always. Some older machines used to have 7-bit byte.

It can be found in <limits.h>.


Trying to answer both the explicit question (what is CHAR_BIT) and the implicit question (how does this work) in the original question.


A char in C and C++ represents the smallest unit of memory the C program can address*

CHAR_BIT in C and C++ represents the number of bits in a char. It must always be at least 8 due to other requirements on the char type. In practice on all modern general purpose computers it is exactly 8 but some historic or specialist systems may have higher values.

Java has no equivilent of CHAR_BIT or sizeof, there is no need for it as all primitive types in Java are fixed size and the internal structure of objects is opaque to the programmer. If translating this code to Java you can simply replace "sizeof(int) * CHAR_BIT - 1" by the fixed value 31.

In this particular code it is being used to calculate the number of bits in an int. Be aware that this calculation assumes that the int type doesn't contain any padding bits.

Assuming that your compiler chooses to sign extend on bit shifts of signed numbers and assuming your system uses 2s complement representation for negative numbers this means that "MASK" will be 0 for a positive or zero value and -1 for a negative value.

To negate a twos complement number we need to perform a bitwise not and then add one. Equivilently we can subtract one and then bitwise negate it.

Again assuming twos complement representation -1 is represented by all ones, so exclusive or with -1 is equivilent to bitwise negation.

So when v is zero the number is left alone, when v is one it is negated.

Something to be aware of is that signed overflow in C and C++ is undefined behaviour. So using this ABS implementaion on the most negative value leads to undefined behaviour. This can be fixed by adding casts such that the final line of the program is evaluated in unsigned int.

* Which is usually but not nesacerally the same as the smallest unit of memory the hardware can address. An implementation can potentially combine multiple units of hardware-addressable memory into one unit of program-addressable memory or split one unit of hardware addressable memory into multiple units of program-addresable memory.


You should be aware that this code depends on the implementation-defined behavior of right bitshift on signed types. gcc promises to always give the sane behavior (sign-bit-extension) but ISO C allows the implementation to zero-fill the upper bits.

One way around this problem:

#ifdef HAVE_SIGN_EXTENDING_BITSHIFTint const mask = v >> sizeof(int) * CHAR_BIT - 1;#elseint const mask = -((unsigned)v >> sizeof(int) * CHAR_BIT - 1);#endif

Your Makefile or config.h etc. can define HAVE_SIGN_EXTENDING_BITSHIFT at build time depending on your platform.