Changing 4 bits in a number with a given shift - c

I have a decimal number that I need to manipulate 4 bits in with a given shift.
For example, if the number is 208, or 11010000 binary, and I want to change 4 bits to 1101 with a shift of 2. The new number will be 244.
When the change was: 11110100.
Here's my code:
void change_bit(int num, int bit, int shift)
{
num = (num & (0xfffffff0<<shift)) | (bit << shift);
printf("%d\n", num);
}
The shifting of 0xfffffff0 just adds '0' to the left size.
How can I fix it?

It is easier if you split complex expressions into smaller bits. It does not affect the efficiency of the code but it will be much easier for you read and understand.
unsigned change_bit(unsigned num, unsigned bit, int shift)
{
unsigned mask = ((1U << 4) - 1) << shift; // mask to reset the bits at the position
num &= ~mask; //reset the bits
num |= bit << shift; //set the bits
return num;
}
or more generally
unsigned change_bit(unsigned num, unsigned newval, int shift, int numbits)
{
unsigned mask = ((1 << numbits) - 1) << shift;
num &= ~mask;
num |= newval << shift;
return num;
}
and some test code:
void print(unsigned val)
{
for(unsigned x = 1U << 31; x ; x >>= 1)
{
printf("%d", !!(val & x));
}
printf("\n");
}
int main(void)
{
print(208);
print(change_bit(208, 0b1101, 2));
printf("%d\n", change_bit(208, 0b1101, 2));
}
You should also add some parameters checks.

Related

Trying to convert decimal long to binary using a char mask, but I can't succeed

long number = 12501;
unsigned char mask = 1 << 7; // create a mask 10000000
for (size_t i=0; i<(sizeof(long)*8); ++i){ // iteration for all bits of long type
if (mask & number){
putchar('1');
} else {
putchar('0');
}
number <<=1; // I shift the most significant bit after every comparison
}
Is it possible to do a binary conversion using a char mask? My current output is: 0110100000000000000000000000000000000000000000000000000000000000
Expected output:
0000000000000000000000000000000000000000000000000011000011010101
Here you have a correct version
void printbin(long number)
{
unsigned long mask = 1LU << (sizeof(unsigned long) * CHAR_BIT - 1); // create a mask 10000000
for (; mask; mask >>= 1){ // iteration for all bits of long type
putchar((number & mask) ? '1' : '0');
}
}
https://godbolt.org/z/Qm8Uqs

Circular shift 28 bits within 4 bytes in C

I have an unsigned char *Buffer that contains 4 bytes, but only 28 of them are relevant to me.
I am looking to create a function that will do a circular shift of the 28 bits while ignoring the remaining 4 bits.
For example, I have the following within *Buffer
1111000011001100101010100000
Say I want to left circular shift by 1 bit of the 28 bits, making it
1110000110011001010101010000
I have looked around and I can't figure out how to get the shift, ignore the last 4 bits, and have the ability to shift either 1, 2, 3, or 4 bits depending on a variable set earlier in the program.
Any help with this would be smashing! Thanks in advance.
Only 1 bit at a time, but this does a 28 bit circular shift
uint32_t csl28(uint32_t value) {
uint32_t overflow_mask = 0x08000000;
uint32_t value_mask = 0x07FFFFFF;
return ((value & value_mask) << 1) | ((value & overflow_mask) >> 27);
}
uint32_t csr28(uint32_t value) {
uint32_t overflow_mask = 0x00000001;
uint32_t value_mask = 0x0FFFFFFE;
return ((value & value_mask) >> 1) | ((value & overflow_mask) << 27);
}
Another version, based on this article. This shifts an artbitrary number of bits (count) within an arbitrarily wide bit field (width). To left shift a value 5 bits in a 23 bit wide field: rotl32(value, 5, 23);
uint32_t rotl32 (uint32_t value, uint32_t count, uint32_t width) {
uint32_t value_mask = ((uint32_t)~0) >> (CHAR_BIT * sizeof(value) - width);
const uint32_t mask = (width-1);
count &= mask;
return value_mask & ((value<<count) | (value>>( (-count) & mask )));
}
uint32_t rotr32 (uint32_t value, uint32_t count, uint32_t width) {
uint32_t value_mask = ((uint32_t)~0) >> (CHAR_BIT * sizeof(value) - width);
const uint32_t mask = (width-1);
count &= mask;
return value_mask & ((value>>count) | (value<<( (-count) & mask )));
}
The above functions assume the value is stored in the low order bits of "value"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
const char *uint32_to_binary(uint32_t x)
{
static char b[33];
b[0] = '\0';
uint32_t z;
for (z = 0x80000000; z > 0; z >>= 1)
{
strcat(b, ((x & z) == z) ? "1" : "0");
}
return b;
}
uint32_t reverse(uint32_t value)
{
return (value & 0x000000FF) << 24 | (value & 0x0000FF00) << 8 |
(value & 0x00FF0000) >> 8 | (value & 0xFF000000) >> 24;
}
int is_big_endian(void)
{
union {
uint32_t i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1;
}
int main(int argc, char** argv) {
char b[] = { 0x98, 0x02, 0xCA, 0xF0 };
char *buffer = b;
//uint32_t num = 0x01234567;
uint32_t num = *((uint32_t *)buffer);
if (!is_big_endian()) {
num = reverse(*((uint32_t *)buffer));
}
num >>= 4;
printf("%x\n", num);
for(int i=0;i<5;i++) {
printf("%s\n", uint32_to_binary(num));
num = rotl32(num, 3, 28);
}
for(int i=0;i<5;i++) {
//printf("%08x\n", num);
printf("%s\n", uint32_to_binary(num));
num = rotr32(num, 3, 28);
}
unsigned char out[4];
memset(out, 0, sizeof(unsigned char) * 4);
num <<= 4;
if (!is_big_endian()) {
num = reverse(num);
}
*((uint32_t*)out) = num;
printf("[ ");
for (int i=0;i<4;i++) {
printf("%s0x%02x", i?", ":"", out[i] );
}
printf(" ]\n");
}
First you mask the top four most significant bits
*(buffer + 3) &= 0x0F;
Then you can perform the circular shift of the remaining 28 bits by x bits.
Note: This will work for little endian architecture(x86 Pc's and most microcontrollers)
[...] that contains 4 bytes, but only 28 of them [...]
We got it, but...
I guess that you mis-typed the second number of your example. Or you '''ignore''' 4 bits from left and right so you're actually interrested in 24 bits? Anyway:
Use same principle as in
Circular shift in c.
You need to convert your Buffer to a 32 bit arithmetic type, before. Maybe uint32_t is what you need?
Where did Buffer get his value? You may need to think about endianness.

Can someone explain how this bitMask code works?

This is code that my partner came up with but for some reason I can't get a hold of him to ask him how it's suppose to work. I've been through it many times now and can't seem to get the answer I'm suppose to get.
/**
* bitMask - Generate a mask consisting of all 1's
* lowbit and highbit
* Examples: bitMask(5,3) = 0x38
* Assume 0 <= lowbit <= 31, and 0 <= highbit <= 31
* If lowbit > highbit, then mask should be all 0's
* Legal ops: ! ~ & ^ | + << >>
*/
int bitMask(int highbit, int lowbit) {
int i = ~0;
return ~(i << highbit << 1) & (i << lowbit);
}
This function is actually incorrect: for large values of highbit and lowbit, it may have implementation specific behavior or even undefined behavior. It should use and return unsigned types:
unsigned bitMask(int highbit, int lowbit) {
unsigned i = ~0U;
return ~(i << highbit << 1) & (i << lowbit);
}
Here are the steps:
i = ~0U; sets i to all bits 1.
i << highbit shifts these bits to the left, inserting highbit 0 bits in the low order bits.
i << highbit << 1 makes room for one more 0 bit. One should not simplify this expression as i << (highbit + 1) because such a bit shift is implementation defined if highbit + 1 becomes larger or equal to the number of bits in the type of i.
~(i << highbit << 1) complements this mask, creating a mask with highbit + 1 bits set in the low order positions and 0 for the higher bits.
i << lowbit creates a mask with lowbit 0 bits and 1 in the higher positions.
~(i << highbit << 1) & (i << lowbit) computes the intersection of these 2 masks, result has 1 bits from bit number lowbit to bit number highbit inclusive, numbering the bits from 0 for the least significant.
examples:
bitMask(31, 0) -> 0xFFFFFFFF.
bitMask(0, 0) -> 0x00000001.
bitMask(31, 16) -> 0xFFFF0000.
bitMask(15, 0) -> 0x0000FFFF.
This numbering method is used in hardware specifications. I personally prefer a different method where one specifies the number of bits to skip and the number of bits to set, more consistent with bit-field specifications:
unsigned bitSpec(int start, int len) {
return (~0U >> (32 - len)) << start;
}
and the same examples:
bitSpec(0, 32) -> 0xFFFFFFFF.
bitSpec(0, 1) -> 0x00000001.
bitSpec(16, 16) -> 0xFFFF0000.
bitSpec(0, 16) -> 0x0000FFFF.
In your case, given the description included with your function, the function is doing exactly what you seem to intend it to do. The primary problem is you are using int instead of unsigned int. That will cause problems with sign extension. (not to mention the lack of definition for signed shifts in C).
A simple conversion to unsigned will show you it is operating as you expect:
Short example:
#include <stdio.h>
#include <stdlib.h>
unsigned int bitMask (unsigned int highbit, unsigned int lowbit) {
unsigned int i = ~0;
return ~(i << highbit << 1) & (i << lowbit);
}
char *binstr (unsigned long n, unsigned char sz, unsigned char szs, char sep) {
static char s[128 + 1] = {0};
char *p = s + 128;
unsigned char i;
for (i = 0; i < sz; i++) {
p--;
if (i > 0 && szs > 0 && i % szs == 0)
*p-- = sep;
*p = (n >> i & 1) ? '1' : '0';
}
return p;
}
int main (int argc, char **argv) {
unsigned high = argc > 1 ? (unsigned)strtoul (argv[1], NULL, 10) : 5;
unsigned low = argc > 2 ? (unsigned)strtoul (argv[2], NULL, 10) : 3;
printf ("%s\n", binstr (bitMask (high, low), 32, 8, '-'));
return 0;
}
Output
$ ./bin/bitmask
00000000-00000000-00000000-00111000
$ ./bin/bitmask 10 3
00000000-00000000-00000111-11111000
$ ./bin/bitmask 31 5
11111111-11111111-11111111-11100000
$ ./bin/bitmask 4 8
00000000-00000000-00000000-00000000

how do I rotate all bits to left and the last bit to the right in c

I have to shift all bits from x 1 position to the left and the first bit of the left to bit position 0 (most right). I was wondering what I am doing wrong and could you help me with it.
int rotateleft (int x);
int main ()
{
int getal,result;
printf("Enter a number :\n");
scanf("%i",&getal);
result=rotateleft(getal);
printf("result after rotation: %08x", result );
return 0;
}
int rotateleft (int x)
{
int rbit;
rbit = x <<1;
return rbit;
}
From wikipedia:
unsigned int rotl(unsigned int value, int shift) {
return (value << shift) | (value >> (sizeof(value) * CHAR_BIT - shift));
}
Before you do your shifting, get the top bit and save it. Then after the shifting you set that saved bit in the lowest bit in the (shifted) value.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
uint16_t rotate(uint16_t num, uint16_t shBits);
int main(void)
{
uint16_t num = 0x0088, res;
printf("%x\n", num);
res = rotate(num, 3);
printf("%x\n", res);
return 0;
}
uint16_t rotate(uint16_t num, uint16_t shBits)
{
shBits = ( (shBits < 0) ? -shBits : shBits) ; // make sure that n is not a negative number
shBits = shBits % 16; // ensure that the shift value is less than 32
// move shBits most significant bits to the right (LSBs)
// 0x0088 >> (16 - 3) => 0000 0000 0000 0100
// bits = 0000 0000 0000 0100
uint16_t bits = num >> (16 - shBits);
// (num = 0x0088) >> 3 =>0x0011
num >>= shBits;
printf("num %x\n", num);
printf("Bits %x\n", bits);
shBits <<= num; // postion the shifted bints to the right location
num |=shBits;
printf("num %x\n", num);
return (num);
}
Input is 0x0088 (0000 0000 1000 1000)
rotate by 3
Output 0x0011 (0000 0000 0001 0001)
The idea is to use a mask to filer out the left most bit [usually MSB] and save it. Then apply required shift and put back the stored bit in the right most bit location [Usually LSB] shifted value.
In your code, there is one more thing to notice, there is no return statement in int rotateleft (int x) function. After doing all the computation correct, you'll not get the output. Add one return rbit.
int rotateleft (int x)
{
int rbit;
int bit;
bit = !!(x & (1 << 31));
x = x <<1;
x |= bit;
return x;
}
Shift the number by 1 to the left then use the Bitwise OR to add the last bit to the start of the new number:
10000000000010010110100001100010 // i
00000000000100101101000011000100 // i << 1
00000000000000000000000000000001 // i >> 31
| | || | || | |
00000000000100101101000011000101 // (i << 1) | (i >> 31)
So your function will be: Live Demo
unsigned int rotateLeft(unsigned int i)
{
unsigned int j = (i << 1) | (i >> 31);
return j;
}

replace byte in 32 bit number

I have a function called replaceByte(x,n,c) that is to replace byte n in x with c with the following restrictions:
Bytes numbered from 0 (LSB) to 3 (MSB)
Examples: replaceByte(0x12345678,1,0xab) = 0x1234ab78
You can assume 0 <= n <= 3 and 0 <= c <= 255
Legal ops: ! ~ & ^ | + << >>
Max ops: 10
int replaceByte(int x, int n, int c) {
int shift = (c << (8 * n));
int mask = 0xff << shift;
return (mask & x) | shift;
}
but when I test it I get this error:
ERROR: Test replaceByte(-2147483648[0x80000000],0[0x0],0[0x0]) failed...
...Gives 0[0x0]. Should be -2147483648[0x80000000]
after realizing that * is not a legal operator I have finally figured it out...and if you are curious, this is what I did:
int replaceByte(int x, int n, int c) {
int mask = 0xff << (n << 3);
int shift = (c << (n << 3));
return (~mask & x) | shift;
}
Since this looks like homework I'm not going to post code, but list the steps you need to perform:
Cast c into a 32-bit number so you don't lose any bits while shifting
Next, shift c by the appropriate number of bits to the left (if n==0 no shifting, if n==1 shift by 8 etc.)
Create a 32-bit bitmask that will zero the lowest 8 bits of x, then shift this mask by the same amount as the last step
Perform bitwise AND of the shifted bitmask and x to zero out the appropriate bits of x
Perform bitwise OR (or addition) of the shifted c value and x to replace the masked bits of the latter
Ahh... You are almost there.
Just change
return (mask & x) | shift;
to
return (~mask & x) | shift;
The mask should contain all ones except for the region to be masked and not vice versa.
I am using this simple code and it works fine in gcc
#include<stdio.h>
int replaceByte(int x, int n, int c)
{
int shift = (c << (8 * n));
int mask = 0xff << shift;
return (~mask & x) | shift;
}
int main ()
{
printf("%X",replaceByte(0x80000000,0,0));
return 0;
}
Proper solution is for c = 0 as well:
int replaceByte(int x, int n, int c)
{
int shift = 8 * n;
int value = c << shift;
int mask = 0xff << shift;
return (~mask & x) | value;
}

Resources