Changing bits in an int in C? - c

So I have a 16 bit number. Say that the variable name for it is Bits. I want to make it so that Bits[2:0] = 001, 100, and 000, without changing anything else. I'm not sure how to do it, because all I can think of is ORing the bit I want to be a 1 with 1, but I'm not sure how to clear the other bits so that they're 0. If anyone has advice, I'd appreciate it. Thanks!

To clear certain bits, & with the inverse of the bits to be cleared. Then you can | in the bits you want.
In this case, you want to zero out the lower three bits (111 in binary or 7 in decimal), so we & with ~7 to clear those bits.
Bits = (Bits & ~7) | 1; // set lower three bits of Bits to 001

union structures allow the ability to specify the number of bits a variable has and address each bit of a bigger variable individually.
union {
short value;
struct {
unsigned char bit0 : 1;
unsigned char bit1 : 1;
unsigned char bit2 : 1;
unsigned char bit3 : 1;
unsigned char bit4 : 1;
unsigned char bit5 : 1;
unsigned char bit6 : 1;
unsigned char bit7 : 1;
unsigned char bit8 : 1;
unsigned char bit9 : 1;
unsigned char bit10 : 1;
unsigned char bit11 : 1;
unsigned char bit12 : 1;
unsigned char bit13 : 1;
unsigned char bit14 : 1;
unsigned char bit15 : 1;
} bits;
} var;
Now you have a variable named var that hold a 16-bit integer which can be referenced by var.value, and you have access to each individual bit of this variable by acessing var.bits.bit0 through var.bits.bit15.
By setting var.value = 0; all bits are set to 0 too. By setting var.bits.bit0 = 1; you automatically change the value of var.value to 0x8000, or as seen in binary, 1000000000000000.
If you intention is change only the 3 last bits, you can simplify the structure to something more like this:
union {
short value;
struct {
unsigned short header : 13;
unsigned char bit13 : 1;
unsigned char bit14 : 1;
unsigned char bit15 : 1;
} bits;
} var;
Now you have the var.bits.header, that is a 13-bits variable, and 3 other 1-bit variables you can play with.
But notice C++ does not support this kind of structure, so for best C to C++ portability you might prefer to use bitwise operations instead as proposed by #nneonneo.

Related

Why am I losing these bits while defining structs in unions

I have the following problem, I am assigning a number of bits within structures that are in a union.I trying to recombine them with a separate structure in that same union. However, when I assign mvUpper in Individual I lose that data or a significant bit based on the value I am assigning in Individual.(Please note I only lose data upon the portions I recombine in notIndividual) Please disregard the name, this was my investigation of unions before implementation.
#include <stdio.h>
#include <string.h>
typedef union testing
{
struct Individual
{
unsigned short mt : 10;
unsigned short mlbl : 3;
unsigned short mvUpper :3;
unsigned short mvLower :3;
unsigned short mlUpper :2;
unsigned short mlLower :5;
}Individual;
struct bE
{
unsigned int woo: 26;
}bE;
struct notIndividual
{
unsigned short mt : 10;
unsigned short mlbl : 3;
unsigned short mv :6 ;
unsigned short ml : 7;
}notIndividual;
} testing;
int main(int argc, char* argv[]){
testing dothis;
memset(&dothis,0,(sizeof(dothis)));
printf("THIS IS THE SIZE of union%lu\n",sizeof(dothis));
//printf("SIZE %d",sizeof(dothis.Individual));
//printf("NOT SIZE %d",sizeof(dothis.notIndividual));
dothis.Individual.mvUpper=3;
printf("Testing MT%u\n",dothis.Individual.mt);
printf("Testing MLBL %u\n",dothis.Individual.mlbl);
printf("Testing MVUpper %u\n",dothis.Individual.mvUpper);
printf("Testing MVLower %u\n",dothis.Individual.mvLower);
printf("Testing ML Upper %u\n",dothis.Individual.mlUpper);
printf("Testing ML Lower %u\n",dothis.Individual.mlLower);
printf("Testing Mt %u\n",dothis.notIndividual.mt);
printf("Testing Mlbl %u\n",dothis.notIndividual.mlbl);
printf("Testing MV %u \n",dothis.notIndividual.mv);
printf("Testing ML %u\n",dothis.notIndividual.ml);
printf("THIS IS THE WORD %u\n", dothis.bE.woo>>21);
return 1;
}
This is the output I can't understand
THIS IS THE SIZE of union4
Testing MT0
Testing MLBL 0
Testing MVUpper 3
Testing MVLower 0
Testing ML Upper 0
Testing ML Lower 0
Testing Mt 0
Testing Mlbl 0
Testing MV 0
Testing ML 0
THIS IS THE WORD 0
I was trying to test out an easy way of bit-shifting through unions.
To preface, the organization of bitfields within a struct is implementation defined, so you can't reliably depend on a certain layout. That being said, here's what it most likely happening.
The base type for each of your bitfields is unsigned short. So the compiler will try to group each of the bitfields into units of that size.
For the first struct, the layout is as follows:
struct Individual
{
unsigned short mt : 10; // 10 bits used in unit 0
unsigned short mlbl : 3; // 13 bits used in unit 0
unsigned short mvUpper :3; // 16 bits used in unit 0
unsigned short mvLower :3; // 3 bits used in unit 1
unsigned short mlUpper :2; // 5 bits used in unit 1
unsigned short mlLower :5; // 10 bits used in unit 1
}Individual;
And the second:
struct notIndividual
{
unsigned short mt : 10; // 10 bits used in unit 0
unsigned short mlbl : 3; // 13 bits used in unit 0
unsigned short mv :6 ; // 6 bits used in unit 1 (not enough in unit 0)
unsigned short ml : 7; // 13 bits used in unit 1
}notIndividual;
If you change all of your bitfields to have base type unsigned int, the bitfields will be more packed and you'll get the result you expect.

Negation error in 16 bit 2's complement code

It's a code for finding 2's complement. When num is char, it works fine for 8 bit. But when it is unsigned int for 16-bits numbers. Code doesn't work.
Can you guide?
#include<stdio.h>
#define ISNEGATIVE(num) num & 0x80
#define TWO_COMP(num) (~num) + 1
int main()
{
unsigned int num;
num = 0xFFFF;
if(ISNEGATIVE(num))
printf("1's = %d, 2's = %d", ~num, TWO_COMP(num));
return 0;
}
Output :
1's = -65536, 2's = -65535
An unsigned int is a 32-bit variable on most computers. If you want to use a 16-bit value use uint16_t by preference, or unsigned short. You also need to use the appropriate half-word specifiers in your printf call:
#include <stdio.h>
#include <stdint.h>
#define ISNEGATIVE(num) num & 0x8000
#define TWO_COMP(num) (~num) + 1
int main()
{
/*unsigned short num;*/
uint16_t num;
num = 0xFFFF;
if(ISNEGATIVE(num))
printf("1's = %hd, 2's = %hd", ~num, TWO_COMP(num));
return 0;
}
This outputs
1's = 0, 2's = 1
The 2 primary issues are:
the width of the mask needs to match the width of the number being looked at:
this algorithm should be limited to testing signed types,
Width of char AKA int8_t is 8 bits, so 0x80 works fine.
Width of short int AKA int16_t is 16 bits so requires 0x8000
Width of int AKA int32_t is 32 bits so would require 0x80000000
and so on...
Because num in your code is 16 bits wide, the line:
#define ISNEGATIVE(num) num & 0x80
Should be:
#define ISNEGATIVE(num) num & 0x8000
Just as important, because the value stored in the MSB of an unsigned type does not make the value negative, the algorithm should only be used to evaluate signed types.
unsigned int num;
Should be:
int num;

How do I convert and break a 2 byte integer into 2 different chars in C?

I want to convert an unsigned int and break it into 2 chars. For example: If the integer is 1, its binary representation would be 0000 0001. I want the 0000 part in one char variable and the 0001 part in another binary variable. How do I achieve this in C?
If you insist that you have a sizeof(int)==2 then:
unsigned int x = (unsigned int)2; //or any other value it happens to be
unsigned char high = (unsigned char)(x>>8);
unsigned char low = x & 0xff;
If you have eight bits total (one byte) and you are breaking it into two 4-bit values:
unsigned char x=2;// or whatever
unsigned char high = (x>>4);
unsigned char low = x & 0xf;
Shift and mask off the part of the number you want. Unsigned ints are probably four bytes, and if you wanted all four bytes, you'd just shift by 16 and 24 for the higher order bytes.
unsigned char low = myuint & 0xff;
unsigned char high = (myuint >> 8) & 0xff;
This is assuming 16 bit ints check with sizeof!! On my platform ints are 32bit so I will use a short in this code example. Mine wins the award for most disgusting in terms of pulling apart the pointer - but it also is the clearest for me to understand.
unsigned short number = 1;
unsigned char a;
a = *((unsigned char*)(&number)); // Grab char from first byte of the pointer to the int
unsigned char b;
b = *((unsigned char*)(&number) + 1); // Offset one byte from the pointer and grab second char
One method that works is as follows:
typedef union
{
unsigned char c[sizeof(int)];
int i;
} intchar__t;
intchar__t x;
x.i = 2;
Now x.c[] (an array) will reference the integer as a series of characters, although you will have byte endian issues. Those can be addressed with appropriate #define values for the platform you are programming on. This is similar to the answer that Justin Meiners provided, but a bit cleaner.
unsigned short s = 0xFFEE;
unsigned char b1 = (s >> 8)&0xFF;
unsigned char b2 = (((s << 8)>> 8) & 0xFF);
Simplest I could think of.
int i = 1 // 2 Byte integer value 0x0001
unsigned char byteLow = (i & 0x00FF);
unsinged char byteHigh = ((i & 0xFF00) >> 8);
value in byteLow is 0x01 and value in byteHigh is 0x00

Forcing alignment of C bitfield using a union

I was wondering if it is possible to force the alignment of bitfield in C. Using the variables in the code below I know that writing to _align_bytes then reading from bits is undefined (and vice-versa) because it is implementation depended. Is the code below a valid method to "persuade" bits to be stored contiguously in something that is the size of unsigned short? I believe that (minus any endian issues) this code is correct... but bitfields and unions are the two C topics I am least familiar with.
I am doing a low level micro-controller project and would like an easy method of reading configuration bits without a ton of bit masking. Thanks for any tips and suggestions.
Sam
P.S. Please disregard any assumptions I make about endianness as this project I am working on is very low level and not intended to be ported to other devices/platforms.
#include <stdio.h>
#include <assert.h>
typedef union packet {
struct {
unsigned int bit0 : 1;
unsigned int bit1 : 1;
unsigned int bit2 : 1;
unsigned int bit3 : 1;
unsigned int bit4 : 1;
unsigned int bit5 : 1;
unsigned int bit6 : 1;
unsigned int bit7 : 1;
unsigned int bit8 : 1;
unsigned int bit9 : 1;
unsigned int bit10 : 1;
unsigned int bit11 : 1;
unsigned int bit12 : 1;
unsigned int bit13 : 1;
unsigned int bit14 : 1;
unsigned int bit15 : 1;
} bits;
unsigned short _align_bytes;
} packet_t;
int main(int argc, char *argv[]) {
assert(sizeof(unsigned short) == 2);
unsigned short data = 0xA05F;
packet_t *p = (packet_t *)&data;
printf("%u", p->bits.bit15);
printf("%u", p->bits.bit14);
printf("%u", p->bits.bit13);
printf("%u", p->bits.bit12);
printf("%u", p->bits.bit11);
printf("%u", p->bits.bit10);
printf("%u", p->bits.bit9);
printf("%u", p->bits.bit8);
printf("%u", p->bits.bit7);
printf("%u", p->bits.bit6);
printf("%u", p->bits.bit5);
printf("%u", p->bits.bit4);
printf("%u", p->bits.bit3);
printf("%u", p->bits.bit2);
printf("%u", p->bits.bit1);
printf("%u", p->bits.bit0);
return 0;
}
This is a common pattern and as far as I know, the answer is yes: the bit fields will be contiguous and occupy the same memory as the _align_bytes field. That's the whole point of a union, right? Different ways of looking at the same memory.
I'm not sure what you mean by "writing to _align_bytes then reading from bits is undefined". The only issue I see is the endianess: bit0 may be the lsb or the msb of _align_bytes. If you don't want it to be portable, then you just need to do a quick test to figure out which it is, and you should be set.
I am not sure, but wouldn't this violate strict aliasing rules because two pointers of different types are pointing to the same memory location? In C89 and C99 you are not guaranteed to get anything back correctly.
You may want to test this, and if required use -fno-strict-aliasing or something similar for your compiler so that it disables strict aliasing which could cause issues.

How do I extract specific 'n' bits of a 32-bit unsigned integer in C?

Could anyone tell me as to how to extract 'n' specific bits from a 32-bit unsigned integer in C.
For example, say I want the first 17 bits of the 32-bit value; what is it that I should do?
I presume I am supposed to use the modulus operator and I tried it and was able to get the last 8 bits and last 16 bits as
unsigned last8bitsvalue=(32 bit integer) % 16
unsigned last16bitsvalue=(32 bit integer) % 32
Is this correct? Is there a better and more efficient way to do this?
Instead of thinking of it as 'extracting', I like to think of it as 'isolating'. Once the desired bits are isolated, you can do what you will with them.
To isolate any set of bits, apply an AND mask.
If you want the last X bits of a value, there is a simple trick that can be used.
unsigned mask;
mask = (1 << X) - 1;
lastXbits = value & mask;
If you want to isolate a run of X bits in the middle of 'value' starting at 'startBit' ...
unsigned mask;
mask = ((1 << X) - 1) << startBit;
isolatedXbits = value & mask;
Hope this helps.
If you want n bits specific then you could first create a bitmask and then AND it with your number to take the desired bits.
Simple function to create mask from bit a to bit b.
unsigned createMask(unsigned a, unsigned b)
{
unsigned r = 0;
for (unsigned i=a; i<=b; i++)
r |= 1 << i;
return r;
}
You should check that a<=b.
If you want bits 12 to 16 call the function and then simply & (logical AND) r with your number N
r = createMask(12,16);
unsigned result = r & N;
If you want you can shift the result. Hope this helps
Modulus works to get bottom bits (only), although I think value & 0x1ffff expresses "take the bottom 17 bits" more directly than value % 131072, and so is easier to understand as doing that.
The top 17 bits of a 32-bit unsigned value would be value & 0xffff8000 (if you want them still in their positions at the top), or value >> 15 if you want the top 17 bits of the value in the bottom 17 bits of the result.
There is a single BEXTR (Bit field extract (with register)) x86 instruction on Intel and AMD CPUs and UBFX on ARM. There are intrinsic functions such as _bextr_u32() (link requires sign-in) that allow to invoke this instruction explicitly.
They implement (source >> offset) & ((1 << n) - 1) C code: get n continuous bits from source starting at the offset bit. Here's a complete function definition that handles edge cases:
#include <limits.h>
unsigned getbits(unsigned value, unsigned offset, unsigned n)
{
const unsigned max_n = CHAR_BIT * sizeof(unsigned);
if (offset >= max_n)
return 0; /* value is padded with infinite zeros on the left */
value >>= offset; /* drop offset bits */
if (n >= max_n)
return value; /* all bits requested */
const unsigned mask = (1u << n) - 1; /* n '1's */
return value & mask;
}
For example, to get 3 bits from 2273 (0b100011100001) starting at 5-th bit, call getbits(2273, 5, 3)—it extracts 7 (0b111).
For example, say I want the first 17 bits of the 32-bit value; what is it that I should do?
unsigned first_bits = value & ((1u << 17) - 1); // & 0x1ffff
Assuming CHAR_BIT * sizeof(unsigned) is 32 on your system.
I presume I am supposed to use the modulus operator and I tried it and was able to get the last 8 bits and last 16 bits
unsigned last8bitsvalue = value & ((1u << 8) - 1); // & 0xff
unsigned last16bitsvalue = value & ((1u << 16) - 1); // & 0xffff
If the offset is always zero as in all your examples in the question then you don't need the more general getbits(). There is a special cpu instruction BLSMSK that helps to compute the mask ((1 << n) - 1).
If you need the X last bits of your integer, use a binary mask :
unsigned last8bitsvalue=(32 bit integer) & 0xFF
unsigned last16bitsvalue=(32 bit integer) & 0xFFFF
This is a briefer variation of the accepted answer: the function below extracts the bits from-to inclusive by creating a bitmask. After applying an AND logic over the original number the result is shifted so the function returns just the extracted bits.
Skipped index/integrity checks for clarity.
uint16_t extractInt(uint16_t orig16BitWord, unsigned from, unsigned to)
{
unsigned mask = ( (1<<(to-from+1))-1) << from;
return (orig16BitWord & mask) >> from;
}
Bitwise AND your integer with the mask having exactly those bits set that you want to extract. Then shift the result right to reposition the extracted bits if desired.
unsigned int lowest_17_bits = myuint32 & 0x1FFFF;
unsigned int highest_17_bits = (myuint32 & (0x1FFFF << (32 - 17))) >> (32 - 17);
Edit: The latter repositions the highest 17 bits as the lowest 17; this can be useful if you need to extract an integer from “within” a larger one. You can omit the right shift (>>) if this is not desired.
#define GENERAL__GET_BITS_FROM_U8(source,lsb,msb) \
((uint8_t)((source) & \
((uint8_t)(((uint8_t)(0xFF >> ((uint8_t)(7-((uint8_t)(msb) & 7))))) & \
((uint8_t)(0xFF << ((uint8_t)(lsb) & 7)))))))
#define GENERAL__GET_BITS_FROM_U16(source,lsb,msb) \
((uint16_t)((source) & \
((uint16_t)(((uint16_t)(0xFFFF >> ((uint8_t)(15-((uint8_t)(msb) & 15))))) & \
((uint16_t)(0xFFFF << ((uint8_t)(lsb) & 15)))))))
#define GENERAL__GET_BITS_FROM_U32(source,lsb,msb) \
((uint32_t)((source) & \
((uint32_t)(((uint32_t)(0xFFFFFFFF >> ((uint8_t)(31-((uint8_t)(msb) & 31))))) & \
((uint32_t)(0xFFFFFFFF << ((uint8_t)(lsb) & 31)))))))
int get_nbits(int num, int n)
{
return (((1<<n)-1) & num);
}
I have another method for accomplishing this. You can use a union of an integer type that has enough bits for your application and a bit field struct.
Example:
typedef thesebits
{
unsigned long first4 : 4;
unsigned long second4 : 4;
unsigned long third8 : 8;
unsigned long forth7 : 7;
unsigned long fifth3 : 3;
unsigned long sixth5 : 5;
unsigned long last1 : 1;
} thesebits;
you can set that struct up to whatever bit pattern you want. If you have multiple bit patterns, you can even use that in your union as well.
typedef thesebitstwo
{
unsigned long first8 : 8;
unsigned long second8 : 8;
unsigned long third8 : 8;
unsigned long last8 : 8;
} thesebitstwo;
Now you can set up your union:
typedef union myunion
{
unsigned long mynumber;
thesebits mybits;
thesebitstwo mybitstwo;
} myunion;
Then you can access the bits you want from any number you assign to the member mynumber:
myunion getmybits;
getmybits.mynumber = 1234567890;
If you want the last 8 bits:
last16bits = getmybits.mybitstwo.last8;
If you want the second 4 bits:
second4bits = getmybits.mybits.second4;
I gave two examples kind of randomly assigned different bits to show. You can set the struct bit-fields up for whatever bits you want to get. I made all of the variables type unsigned long but you can use any variable type as long as the number of bits doesn't exceed those that can be used in the type. So most of these could have been just unsigned int and some even could be unsigned short
The caveat here is this works if you always want the same set of bits over and over. If there's a reason you may need to vary which bits you're looking at to anything, you could use a struct with an array that keeps a copy of the bits like so:
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
typedef struct bits32
{
bool b0 : 1;
bool b1 : 1;
bool b2 : 1;
bool b3 : 1;
bool b4 : 1;
bool b5 : 1;
bool b6 : 1;
bool b7 : 1;
bool b8 : 1;
bool b9 : 1;
bool b10 : 1;
bool b11 : 1;
bool b12 : 1;
bool b13 : 1;
bool b14 : 1;
bool b15 : 1;
bool b16 : 1;
bool b17 : 1;
bool b18 : 1;
bool b19 : 1;
bool b20 : 1;
bool b21 : 1;
bool b22 : 1;
bool b23 : 1;
bool b24 : 1;
bool b25 : 1;
bool b26 : 1;
bool b27 : 1;
bool b28 : 1;
bool b29 : 1;
bool b30 : 1;
bool b31 : 1;
} bits32;
typedef struct flags32 {
union
{
uint32_t number;
struct bits32 bits;
};
bool b[32];
} flags32;
struct flags32 assignarray ( unsigned long thisnumber )
{
struct flags32 f;
f.number = thisnumber;
f.b[0] = f.bits.b0;
f.b[1] = f.bits.b1;
f.b[2] = f.bits.b2;
f.b[3] = f.bits.b3;
f.b[4] = f.bits.b4;
f.b[5] = f.bits.b5;
f.b[6] = f.bits.b6;
f.b[7] = f.bits.b7;
f.b[8] = f.bits.b8;
f.b[9] = f.bits.b9;
f.b[10] = f.bits.b10;
f.b[11] = f.bits.b11;
f.b[12] = f.bits.b12;
f.b[13] = f.bits.b13;
f.b[14] = f.bits.b14;
f.b[15] = f.bits.b15;
f.b[16] = f.bits.b16;
f.b[17] = f.bits.b17;
f.b[18] = f.bits.b18;
f.b[19] = f.bits.b19;
f.b[20] = f.bits.b20;
f.b[21] = f.bits.b21;
f.b[22] = f.bits.b22;
f.b[23] = f.bits.b23;
f.b[24] = f.bits.b24;
f.b[25] = f.bits.b25;
f.b[26] = f.bits.b26;
f.b[27] = f.bits.b27;
f.b[28] = f.bits.b28;
f.b[29] = f.bits.b29;
f.b[30] = f.bits.b30;
f.b[31] = f.bits.b31;
return f;
}
int main ()
{
struct flags32 bitmaster;
bitmaster = assignarray(1234567890);
printf("%d\n", bitmaster.number);
printf("%d\n",bitmaster.bits.b9);
printf("%d\n",bitmaster.b[9]);
printf("%lu\n", sizeof(bitmaster));
printf("%lu\n", sizeof(bitmaster.number));
printf("%lu\n", sizeof(bitmaster.bits));
printf("%lu\n", sizeof(bitmaster.b));
}
The issue with this last example is that it's not compact. The union itself is only 4 bytes, but since you can't do pointers to bit-fields (without complicated and debatably "non-standard" code), then the array makes a copy of each boolean value and uses a full byte for each one, instead of just the bit, so it takes up 9x the total memory space (if you run the printf statement examples I gave, you'll see).
But now, you can address each bit one-by-one and use a variable to index each one, which is great if you're not short on memory.
By using the typedefs above and the assignarray function as a constructor for flags32, you can easily expand to multiple variables. If you're OK just addressing with .b# and not being able to use a variable, you can just define the union as flags32 and omit the rest of the struct. Then you also don't need the assignarray function, and you'll use much less memory.

Resources