Is there a difference between a bit mask and a bit array? - c

I have heard the two terms used interchangeably. Is there a difference?
For example,
unsigned char chessboard : 64; /* Bit mask */
unsigned char chessboard_2 [64]; /* Bit array */

Bit Mask
A bit mask is a binary value that's used to refer to specific bits in an integer value when using bitwise operators. For instance, you might have:
unsigned int low3 = 0x7;
This is a bit mask with the low order 3 bits set. You can then use it to extract a part of a value:
unsigned int value = 030071;
unsigned int value_low3 = value & low3; // result is 01
or to update part of value:
unsigned int newvalue = (value & ~low3) | 5; // result is 030075
Bit Array
A bit array is an unsigned integer, or an array of unsigned integers, that's used to hold a sequence of boolean flags, where each value is in separate bits of the integer(s). If you have lots of boolean values to store, this is saves lots of memory compared to having each of them in a separate array element.
However, there's a tradeoff: in order to access a specific flag, you need to use masking and shifting.
If your bit array is small enough to fit in a single integer, you might declare:
uint32_t bitarray;
Then to access a specific element of it, you use:
bitvalue = (bitarray >> bitnum) & 0x1;
and to set an element:
bitarray |= (1u << bitnum);
and to clear an element:
bitarray &= ~(1u << bitnum);
If the bit array needs multiple words, you declare an array. You get the array index by dividing the bit number by the number of bits in each array element, then use the remainder to determine the bit number within that word and use the above expressions.

None of them is a bitmask. The first is the definition of a bitfield which should only be valid as a struct member and the second is an array of 64 unsigned chars.

Related

Grabbing 'n' binary bits from end of unsigned int in C? Bit masking?

I'm pretty new to C and I seem to be messing up my bitmasking. From what I understand, it's a way to grab or create something of a subset from a binary value.
Say I want to grab the last 8 bits of an unsigned int value, containing 00001111000011110000111100001111.
How would I use AND/OR to grab those last 8?
Here's a more general solution to generate the mask based on how many bits you're interested int.
unsigned int last_n_bits(unsigned int value, int n)
{
unsigned int mask = -1;
if (n < sizeof(unsigned) * CHAR_BIT)
mask = ((1<<n)-1);
return value & mask;
}
You can use the BINARY AND operator for do a binary mask:
unsigned char last_eight_bits = my_number & 0b11111111
Mask-out all bits > 0xff:
value & 0xffu
Say I want to grab the last 8 bits of an unsigned int value, containing
00001111000011110000111100001111.
How would I use AND/OR to grab those last 8?
In this case, you would use AND. The following code will grab the 8 least significant bits:
unsigned int number = 0x0F0F0F0Fu;
unsigned int mask = 0x000000FFu; // set all bits to "1" which you want to grab
unsigned int result = number & mask; // result will be 0x0000000F
The &-Operator is used for an AND-Operation with each bit:
00001111000011110000111100001111
AND 00000000000000000000000011111111
------------------------------------
00000000000000000000000000001111
Be aware that "0 AND X = 0" and that "1 AND X = X". You can do further investigation at: https://en.wikipedia.org/wiki/Boolean_algebra.

Calculate bitmask from a given index in a 16 bit architecture

I have a function that accepts an index variable of type unsigned long (this type cannot be changed).
void func(unsigned long index);
I need to convert it to a bitmask such that for index 0 the bitmask will be 1, for index 1 bitmask will be 2, for 2 it will be 4 and so on.
I have done the following:
mask = 1 << index;
The problem is that I'm working with an architecture of 16 bit , therefore unsigned long variables are shown as 32 bit which messes up this variable.
(the lowest 16 bits give me the correct value for mask but the highest 16 bits add extra information which messes this up).
i.e. Instead of getting: mask = 0000000000000001 (16 bit)
I'm getting: xxxxxxxxxxxxxxxx0000000000000001 (32 bits)
Is there another way to calculate this bitmask?
Would appreciate help.
Thank you.
You have the correct approach. However, the problem with your implementation is that the type of 1 in 1 << index expression is int, with implementation-defined representation. Since you are looking for an unsigned long result, use ((unsigned long)1) instead:
unsigned long mask = ((unsigned long)1) << index;
If your platform supports stdint.h and you need a mask of some specific width, use uint32_t instead:
uint32_t mask = UINT32_C(1) << index;
Your basic code is correct, although I notice you didn't specify the type of mask.
If the caller passes a value greater than 15 into index, what are you going to do? It sounds like you have to make the most of a bad situation. Depending on the context you could simply return from func, you could assert, or you could proceed with a mask of zero.
This brings us back to the question of the type of mask. I would define it as unsigned short, uint16 or similar, depending on your environment. But other than that, your first attempt was basically correct. It's just a question of error handling.
uint16 shift = index & 15;
uint16 mask = 1 << shift;

Shifting bit values in C

Say I have the following code:
uint32_t fillThisNum(int16_t a, int16_t b, int16_t c){
uint32_t x = 0;
uint16_t temp_a = 0, temp_b = 0, temp_c = 0;
temp_a = a << 24;
temp_b = b << 4;
temp_c = c << 4;
x = temp_a|temp_b|temp_c;
return x;
}
Essentially what I'm trying to do is fill the 32-bit number with bit information that I can extract at a later time to perform different operations.
Parameter a would hold the first 24 bits of "data", b would hold the next 4 bits of "data" and c would hold the final 4 bits of "data".
I have a couple questions:
Do the parameters have to be the same bit length as the function type, and must they be unsigned?
Can I assign an unsigned int to a signed int? (i.e. uint32_t a = int32_t b;)
Can I fill a 32-bit number with the 16-bit parameters so long they don't exceed the length of the 32-bit return value.
Any advice/tips/hints would be much appreciated, thank you.
A correct way to write this code is:
uint32_t fillThisNum(uint32_t a, uint32_t b, uint32_t c)
{
// mask out the bits we are not interested in
a &= 0xFFFFFF; // save lowest 24 bits
b &= 0xF; // save lowest 4 bits
c &= 0xF; // save lowest 4 bits
// arrange a,b,c within a 32-bit unit so that they do not overlap
return (a << 8) + (b << 4) + c;
}
By using an unsigned type for the parameters, you avoid any issues with signed arithmetic overflow, sign extension, etc.
It's OK to pass signed values as arguments when calling the function, those values will be converted to unsigned.
By using uint32_t as the parameter type then you avoid having to declare any temporary variables or worry about type width when doing your casting. It makes it easier for you to write clear code, this way.
You don't have to do it this way but this is a simple way to make sure you don't make any mistakes.
Do the parameters have to be the same bit length as the function type, and must they be unsigned?
No, the arguments and the return value can be different types.
Can I assign an unsigned int to a signed int? (i.e. uint32_t a = int32_t b;)
Yes, the value will be converted from a signed to an unsigned value. The bits in "b" will stay the same, so while "b" is in 2's complement, "a" will be a positive 32-bit number.
So, for example, let int8_t c = -127. If you perform an assignment uint8_t d = c, then "d" will be 129.
Can I fill a 32-bit number with the 16-bit parameters so long they don't exceed the length of the 32-bit return value.
If by that, you mean the way that you did in your code:
x = temp_a|temp_b|temp_c;
Yes, that is fine, with the caveat that #chux mentioned: you can't shift an n-bit value more than n bits. If you wanted to set bits more significant than bit 15 in x, a way to do this would be to set up one of the temp masks with a 32-bit value instead of a 16-bit one.

C: how to build up a binary integer

I have some logic that I would like to store as an integer. I have 30 "positions" that can be either yes or no and I would like to represent this as an integer. As I am looping through these positions what would be the easiest way to store this information as an integer?
You can use a 32 bit uint:
uint32_t flags = 0;
flags |= UINT32_C(1) << x; // set x'th bit from right
flags &= ~(UINT32_C(1) << x); // unset x'th bit from right
if (flags & UINT32_C(1) << x) // test x'th bit from right
struct{
int flag0:1;
int flag1:1;
...
int flag31:1;
} myFlags;
Using :x in definition of an integer struct member means bitfield with x bits assigned.
You can access each struct member as usual, but the values can only be according to the size in bits (in my example - either 1 or 0 because only 1 bit is available), and the compiler will enforce it. The struct will be (probably, depends on the compiler settings) packed to a total size of integers needed to represent the total bits.
Another option would be using a int and bitwise operators & and | to access specific bits. In this case you have to make sure yourself that setting one bit won't affect another, and that there are no overflows etc.
#define POSITION_A 1
#define POSITION_B 2
unsigned int position = 0;
// set a position
position |= POSITION_A;
// clear a position
position &= = ~(POSITION_A);
Yes, as WTP's comment, you could save all your data in one unsigned int (uint32_t), and access it with AND(&), OR(|), NOT(~).
If saving storage is not a primary concern, however, I recommend not to use this compact technique.
You may need to expand your code to support more than 2 types(yes/no) of answers such as (yes/no/maybe).
You may have more than 30 questions which does not fit into one unsigned int.
If I were you, I'll use some array/list of small int (short or char) to store the values. It's somewhat waste of storage, but much easier to read, and much easier to add more features.

Bit Shifting, Masking or a Bit Field Struct?

I'm new to working with bits. I'm trying to work with an existing protocol, which can send three different types of messages.
Type 1 is a 16-bit structure:
struct digital
{
unsigned int type:2;
unsigned int highlow:1;
unsigned int sig1:5;
unsigned int :1;
unsigned int sig2:7;
};
The first two bits (type, in my struct above) are always 1 0 . The third bit, highlow, determines whether the signal is on or off, and sig1 + sig2 together define the 12-bit index of the signal. This index is split across the two bytes by a 0, which is always in bit 7.
Type 2 is a 32-bit structure. It has a 2-bit type, a 10-bit index and a 16-bit value, interspersed with 0's at positions 27, 23, 15 & 7. A bit-field struct representation would like something like this:
struct analog
{
unsigned int type:2;
unsigned int val1:2;
unsigned int :1;
unsigned int sig1:3;
unsigned int :1;
unsigned int sig2:7;
unsigned int :1;
unsigned int val2:7;
unsigned int :1;
unsigned int val3:7;
};
sig1 & sig2 together form the 10-bit index. val1 + val2 + val3 together form the 16-bit value of the signal at the 10-bit index.
If I understand how to work with the first two structs, I think I can figure out the third.
My question is, is there a way to assign a single value and have the program work out the bits that need to go into val1, val2 and val3?
I've read about bit shifting, bit-field structs and padding with 0's. The struct seems like the way to go, but I'm not sure how to implement it. None of the examples of bit-packing that I've seen have values that are split the way these are. Ultimately, I'd like to be able to create an analog struct, assign an index (i = 252) and a value (v = 32768) and be done with it.
If someone could suggest the appropriate method or provide a link to a similar sample, I'd greatly appreciate it. If it matters, this code will be incorporated into a larger Objective-C app.
Thanks.
Brad
You can do it with a series of shifts, ands, and ors. I have done the 10-bit index part for Type 2:
unsigned int i = 252;
analog a = (analog)(((i << 16) & 0x7f0000) | (i << 17) & 0x7000000);
Essentially, what this code does is shift the 10 bits of interest in int i to the range 16 - 25, then it ands it with the bitmask 0x7f0000 to set bits 22 - 31 to zero. It also shifts another copy of the 10 bits to the range 17 - 26, then it ands it with the bitmask 0x7000000 to set bits 0 - 22 and 26 - 31 to zero. Then it ors the two values together to create your desired zero-separated value.
.. I'm not absolutely sure that I counted the bitmasks correctly, but I hope you've got the idea. Just shift, and-mask, and or-merge.
Edit: Method 2:
analog a;
a.sig1 = (i & 0x7f); // mask out bit 8 onwards
a.sig2 = ((i<<1) & 0x700); // shift left by one, then mask out bits 0-8
On second thought method 2 is more readable, so you should probably use this.
You don't have to do this, this is where the union keyword comes in - you can specify all the bits out at the same time, or by referring to the same bits with a different name, set them all at once.
You shouldn't use C structure bitfields because the physical layout of bitfields is undefined. While you could figure out what your compiler is doing and get your layout to match the underlying data, the code may not work if you switch to a different compiler or even update your compiler.
I know it's a pain, but do the bit manipulation yourself.

Resources