so I'm trying to shift these values left to store all this data into a 64 bit value. Unfortunately the numbers turn negative right at the first shift, what's causing this? Isn't it only suppose to store the first 41 bits of mil_t time into x? Also why would the remainder of serial and userid be zero?
long int gen_id(){
printf("Calling gen_id...\n");
unsigned long int mil_t = 1623638363132;
unsigned long int serial = 10000;
unsigned int rowId = 5;
unsigned int userId = 30000;
printf("Original mil_t: %ld\n", mil_t);
unsigned long int x = mil_t << 41;
printf("GEN_ID | MIL_T shift left 41: %ld\n", x);
unsigned long int tbusMod = userId % serial;
printf("GEN_ID | tbusMod = userId mod serial: %ld\n", tbusMod);
x += tbusMod << (64 - 41 - 13);
printf("GEN_ID | x1 : %ld\n", x);
x += (rowId % 1024);
printf("GEN_ID | x2 : %ld\n", x);
return x;
}
OUTPUT:
Original mil_t: 1623638647191
GEN_ID | MIL_T shift left 41: -4136565053832822784
GEN_ID | tbusMod = userId mod serial: 0
GEN_ID | x1 : -4136565053832822784
GEN_ID | x2 : -4136565053832822779
FINAL: -4136565053832822779
TOTAL BYTES: 68
Your program causes undefined behaviour by using the incorrect format specifier. %ld is only for long int (and not unsigned long int).
Instead use %lu to display x and tbusMod.
30000 divided by 10000 gives quotient 3, remainder 0 .
Related
I have a function that is aimed at getting the value of two chars added together into a short. It seems that the value is getting cut off or mangled.
Here is my code:
char rotate(char a, char b){
unsigned short x = a + b;
printf("init:%hu %hu = %hu\n", (unsigned char)a, (unsigned char)b, (unsigned short)x);
if(x > 255){
x -= 255;
}
return (char) x;
}
unsigned char x = rotate((unsigned char)230, (unsigned char)100);
unsigned char y = rotate((unsigned char )200, (unsigned char)200);
unsigned char z = rotate((unsigned char) 230, (unsigned char)120);
and the results are
init:230 100 = 74
init:200 200 = 65424
init:230 120 = 94
Addition is done with original values and is correct.
unsigned short x = a + b;
Yet display is done with converted values.
printf("init:%hu %hu = %hu\n", (unsigned char)a, (unsigned char)b, ....
Print the char original values.
#if CHAR_MAX <= INT_MAX
printf("a:%d b:%d\n", a, b);
#else
// this is rare
printf("a:%u b:%u\n", a, b);
#endif
OP will see the first addition is init:-26 100 = 74 and the sum of 74 is as expected.
With init:200 200 = 65424, the original char values are -56. -56 + -56 is -112. Assigning -112 to a 16-bit unsigned short (0-65535) adds 65536 and then assigns. -112 + 65536 --> 65424.
I have a byte array represented as
char * bytes = getbytes(object); //some api function
I want to check whether the bit at some position x is set.
I've been trying this
int mask = 1 << x % 8;
y= bytes[x>>3] & mask;
However y returns as all zeros? What am I doing incorrectly and is there an easier way to check if a bit is set?
EDIT:
I did run this as well. It didn't return with the expected result either.
int k = x >> 3;
int mask = x % 8;
unsigned char byte = bytes[k];
return (byte & mask);
it failed an assert true ctest I ran. Byte and Mask at this time where "0002" and 2 respectively when printed from gdb.
edit 2: This is how I set the bits in the first place. I'm just trying to write a test to verify they are set.
unsigned long x = somehash(void* a);
unsigned int mask = 1 << (x % 8);
unsigned int location = x >> 3;
char* filter = getData(ref);
filter[location] |= mask;
This would be one (crude perhaps) way from the top of my head:
#include "stdio.h"
#include "stdlib.h"
// this function *changes* the byte array
int getBit(char *b, int bit)
{
int bitToCheck = bit % 8;
b = b + (bitToCheck ? (bit / 8) : (bit / 8 - 1));
if (bitToCheck)
*b = (*b) >> (8 - bitToCheck);
return (*b) & 1;
}
int main(void)
{
char *bytes = calloc(2, 1);
*(bytes + 1)= 5; // writing to the appropiate bits
printf("%d\n", getBit(bytes, 16)); // checking the 16th bit from the left
return 0;
}
Assumptions:
A byte is represented as:
----------------------------------------
| 2^7 | 2^6 | 2^5 | 2^4 | 2^3 |... |
----------------------------------------
The left most bit is considered bit number 1 and the right most bit is considered the max. numbered bit (16th bit in a 2 byte object).
It's OK to overwrite the actual byte object (if this is not wanted, use memcpy).
I have a 32-bit int and I want to set the first 10 bit to a specific number.
IE
The 32-bit int is:
11101010101010110101100100010010
I want the first 10 bit to be the number 123, which is
0001111011
So the result would be
00011110111010110101100100010010
Does anyone know the easiest way I would be able to do this? I know that we have to do bit-shifting but I'm not good at it so I'm not sure
Thank you!
uint32_t result = (input & 0x3fffff) | (newval << 22);
0x3fffff masks out the highest 10 bits (it has the lowest 22 bits set). You have to shift your new value for the highest 10 bits by 22 places.
Convert inputs to unsigned 32-bit integers
uint32_t num = strtoul("11101010101010110101100100010010", 0, 2);
uint32_t firstbits = 123;
Mask off the lower 32-10 bits. Create mask by shifting a unsigned long 1 22 places left making 100_0000_0000_0000_0000_0000 then decrementing to 11_1111_1111_1111_1111_1111
uint32_t mask = (1UL << (32-10)) - 1;
num &= mask;
Or in firstbits shifted left by 32-10
num |= firstbits << (32-10);
Or in 1 line:
(num & (1UL << (32-10)) - 1) | (firstbits*1UL << (32-10))
Detail about firstbits*1UL. The type of firstbits is not defined by OP and may only be a 16-bit int. To insure code can shift and form an answer that exceeds 16 bits (the minimum width of int), multiple by 1UL to insure the value is unsigned and has at least 32 bit width.
You can "erase" bits (set them to 0) by using a bit wise and ('&'); bits that are 0 in either value will be 0 in the result.
You can set bits to 1 by using a bit wise or ('|'); bits that are 1 in either value will be 1 in the result.
So: and your number with a value where the first 10 bits are 0 and the rest are 1; then 'or' it with the first 10 bits you want put in, and 0 for the other bits. If you need to calculate that value, then a left-shift would be the way to go.
You can also take a mask and replace approach where you zero the lower bits required to hold 123 and then simply | (OR) the value with 123 to gain the final result. You can accomplish the exact same thing with shifts as shown by several other answers, or you can accomplish it with masks:
#include <stdio.h>
#ifndef BITS_PER_LONG
#define BITS_PER_LONG 64
#endif
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
char *binpad2 (unsigned long n, size_t sz);
int main (void) {
unsigned x = 0b11101010101010110101100100010010;
unsigned mask = 0xffffff00; /* mask to zero lower 8 bits */
unsigned y = 123; /* value to replace zero bits */
unsigned masked = x & mask; /* zero the lower bits */
/* show intermediate results */
printf ("\n x : %s\n", binpad2 (x, sizeof x * CHAR_BIT));
printf ("\n & mask : %s\n", binpad2 (mask, sizeof mask * CHAR_BIT));
printf ("\n masked : %s\n", binpad2 (masked, sizeof masked * CHAR_BIT));
printf ("\n | 123 : %s\n", binpad2 (y, sizeof y * CHAR_BIT));
masked |= y; /* apply the final or with 123 */
printf ("\n final : %s\n", binpad2 (masked, sizeof masked * CHAR_BIT));
return 0;
}
/** returns pointer to binary representation of 'n' zero padded to 'sz'.
* returns pointer to string contianing binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits.
*/
char *binpad2 (unsigned long n, size_t sz)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
register size_t i;
for (i = 0; i < sz; i++)
*--p = (n>>i & 1) ? '1' : '0';
return p;
}
Output
$ ./bin/bitsset
x : 11101010101010110101100100010010
& mask : 11111111111111111111111100000000
masked : 11101010101010110101100100000000
| 123 : 00000000000000000000000001111011
final : 11101010101010110101100101111011
How about using bit fields in C combined with a union? The following structure lets you set the whole 32-bit value, the top 10 bits or the bottom 22 bits. It isn't as versatile as a generic function but you can't easily make a mistake when using it. Be aware this and most solutions may not work on all integer sizes and look out for endianness as well.
union uu {
struct {
uint32_t bottom22 : 22;
uint32_t top10 : 10;
} bits;
uint32_t value;
};
Here is an example usage:
int main(void) {
union uu myuu;
myuu.value = 999999999;
printf("value = 0x%08x\n", myuu.value);
myuu.bits.top10 = 0;
printf("value = 0x%08x\n", myuu.value);
myuu.bits.top10 = 0xfff;
printf("value = 0x%08x\n", myuu.value);
return 0;
}
The output is:
value = 0x3b9ac9ff
value = 0x001ac9ff
value = 0xffdac9ff
I wan't to set the last n bits of any given number to 1. I have a number (which is variable in it's lenght) and a variable n.
Example:
12 (dec) set last 2 bits
Output: 15
Now the basic operation should be something like:
return 0b11 | 12;
But how can I make 0b11 variable in length?
Thank you!
Try this:
int SetLastBits(int value,int numOfBits)
{
return value | ((1<<numOfBits)-1);
}
You can set the last n bits of a number to 1 in the following manner:
int num = 5; // number of bits to set to 1
int val = <some_value>;
val |= (1 << num) - 1;
You can do it like this:
uint32_t set_last_n_bits(uint32_t x, uint32_t bits)
{
return x | ((1U << bits) - 1U);
}
This is also a relatively rare case where a macro might be justifiable, on the grounds that it would work with different integer types.
As all others have showed the same approach I will show one more approach
int value;
//...
value |= ~( ~0u << n );
Here is a demonstrative program
#include <stdio.h>
int set_bits( int x, size_t n )
{
return x | ~( ~0u << n );
}
int main(void)
{
int x = 12;
printf( "%d\t%d\n", x, set_bits( x, 2 ) );
return 0;
}
The output is
12 15
I have a number that is "significant byte", it may be 0 or 255.
Which means 0 or -1.
How to convert 255 to -1 in one time.
I have a function that doesn't works for me:
acc->x = ((raw_data[1]) << 8) | raw_data[0];
Assuming that every 8th bit set to 1 means negative (254 == -2) then a widening conversion from signed types should do:
int n = (signed char)somebyte;
so
unsigned char rawdate[2] = ...;
int msbyte = (signed char)rawdata[1];
acc->x = (msbyte << 8) | (raw_data[0] & 0xFF);
I am not sure what is required but here are the rules for arithmetic conversions of integers.
If an integer is assigned to another lower bit integer, the data will be truncated.
Example:
struct A {
int c1 : 8;
unsigned c2 : 8;
} a;
int main()
{
short int i = 255; // right 8 bits containing all bits set
a.c1 = i; // or a.c1 = 255. casting not required.
a.c2 = i; // same as above.
// prints -1, 255
printf("c1: %d c2: %d\n", a.c1, a.c2);
i = 511; // 9 number of 1 bits
a.c1 = i; // left 9th bit will be truncated. casting not required.
a.c2 = i; // same as above
// prints -1, 255
printf("c1: %d c2: %d\n", a.c1, a.c2);
return 0;
}
If a signed 8 bit integer (or char) is assigned to higher bit integer (say int), it's sign bit will be shifted.
ex:
char c = 255; // which is -1
int i = c; // i is now -1. sign bit will be shifted to 32nd bit.