C++ write a number on two bytes - c++

I am new to the low level c++, and I find it a bit hard to understand how to manipulate bits. I am trying to do the following to use in a compression algorithm I am trying to make:
unsigned int num = ...;//we want to store this number
unsigned int num_size = 3;//this is the maximum size of the number in bits, and
//can be anything from 1 bit to 32
unsigned int pos = 7;//the starting pos on the 1st bit.
//this can be anything from 1 to 8
char a;
char b;
if the num_size is 3 and pos is 7 for example, we must store num, on the 7th and 8th bit of a and on the 1st bit of b.

How about just?
a = num << (pos-1);
b = ((num << (pos-1)) & 0xFF00) >> 8;
To read num back just
num = ((unsigned int)a + ((unsigned int b) << 8)) >> (pos - 1);
Note, this doesn't do any sanity checks, such as whether all the relevant bits fit in a and b, you'll have to do that yourself.

For this specific test case, the highest number that fits into 2 unsigned char is actually 65535.
#include <iostream>
unsigned char high(int input)
{
return (input >> 8) & 0xFF;
}
unsigned char low(int input)
{
return input & 0xFF;
}
int value(unsigned char low, unsigned char high)
{
return low | (high << 8);
}
int main()
{
int num = 65535;
unsigned char l = low(num);
unsigned char h = high(num);
int val = value(l, h);
std::cout<<"l: "<<l<<" h: "<<h<<" val: "<<val;
}

Related

Convert unsigned char array of characters to int C++

How can I convert an unsigned char array that contains letters into an integer. I have tried this so for but it only converts up to four bytes. I also need a way to convert the integer back into the unsigned char array .
int buffToInteger(char * buffer)
{
int a = static_cast<int>(static_cast<unsigned char>(buffer[0]) << 24 |
static_cast<unsigned char>(buffer[1]) << 16 |
static_cast<unsigned char>(buffer[2]) << 8 |
static_cast<unsigned char>(buffer[3]));
return a;
}
It looks like you're trying to use a for loop, i.e. repeating a task over and over again, for an in-determinant amount of steps.
unsigned int buffToInteger(char * buffer, unsigned int size)
{
// assert(size <= sizeof(int));
unsigned int ret = 0;
int shift = 0;
for( int i = size - 1; i >= 0, i-- ) {
ret |= static_cast<unsigned int>(buffer[i]) << shift;
shift += 8;
}
return ret;
}
What I think you are going for is called a hash -- converting an object to a unique integer. The problem is a hash IS NOT REVERSIBLE. This hash will produce different results for hash("WXYZABCD", 8) and hash("ABCD", 4). The answer by #Nicholas Pipitone DOES NOT produce different outputs for these different inputs.
Once you compute this hash, there is no way to get the original string back. If you want to keep knowledge of the original string, you MUST keep the original string as a variable.
int hash(char* buffer, size_t size) {
int res = 0;
for (size_t i = 0; i < size; ++i) {
res += buffer[i];
res *= 31;
}
return res;
}
Here's how to convert the first sizeof(int) bytes of the char array to an int:
int val = *(unsigned int *)buffer;
and to convert in back:
*(unsigned int *)buffer = val;
Note that your buffer must be at least the length of your int type size. You should check for this.

Writing 4 bits to a binary file with ofstream

If I have an unsigned integer between 0 - 16 and I want to write it to a binary file without writing a whole byte to it, how would one shift bits to achieve it?
0-16 means I only need 4 bits, so I should be able to store 2 different numbers in a single byte right?
The following code writes 1 number to 1 byte:
std::ofstream file;
file.open("test.bin", std::ios::binary|std::ios::out);
char oneByteNum = (char)fourByteNum; // Converting from some 4 byte integer to a 1 byte char
file.write(&oneByteNum ,sizeof(char));
Using bitshifts, how can I achieve 2 numbers in 1 byte?
I imagine reading the number out of the byte would be a similar, inverse 2 step process too?
char oneByteWithTwoNums = (oneByteNum1 << 4) + (oneByteNum2 & 0x0f);
Try this:
compacted = first_number * 0x10 + second-number;
To expand:
second_number = compacted & 0x0F;
first_number = compacted >> 4;
I wrote up a quick example:
#include <iostream>
typedef unsigned char byte;
byte pack(unsigned int num1, unsigned int num2) {
// Our byte has the form 0b00000000
// We want the first four bits to be filled with num1
byte packed = num1 << 4;
// We want the last four bits to be filled with num2
// but, we don't want to overwrite the top four bits, so
// we mask it with 0x0F (0b0001111)
packed |= num2 & 0x0F;
return packed;
}
void unpack(byte b, unsigned int& num1, unsigned int& num2) {
// Extract the first four bits of our byte
num1 = b >> 4;
// Mask off the first four bits of our byte to get only
// the last four bits
num2 = b & 0x0F;
}
int main() {
unsigned int num1 = 5; // As an example
unsigned int num2 = 15; // As an example
byte b = pack(num1, num2);
unsigned int num3;
unsigned int num4;
unpack(b, num3, num4);
std::cout << num3 << std::endl;
std::cout << num4 << std::endl;
return 0;
}
You'll probably want to add checks in your pack/unpack methods to ensure someone doesn't try passing in a value other than [0-15].

Efficiency of extracting a bit from byte

I'm extracting the 8th bit from a byte in C. Here is my example.
register unsigned char byte;
int pos = 7;
int x =(byte >> pos) & 1; //Method I
int y =(byte & 0x80) >> pos; //Method II
Both techniques will result in the same output, but is one of the methods more efficient than the other?
Both will be the same. Both AND and SHR instructions are 1-clock instructions on intel CPUs.
Bitwise operations a basically one of the fastest things you'll find on a computer. I'd imagine that any difference would be incredibly minor, such that it doesn't really matter.
If you know the bit you are extracting at compile-time, then either method should have approximately the same speed:
unsigned char val;
const int pos = 4;
...
int x = (val >> pos) & 1;
int y = (val & 0x10) >> pos;
However if you are calculating the position at runtime and not as a constant, doing the AND last should be faster:
unsigned char val;
int pos;
...
/* requires only a shift and AND */
int x = (val >> pos) & 1;
/* requires two shifts and AND */
int y = (val & (1 << pos)) >> pos;

Set upper and lower bytes of an (short int) in C++

i have problem for setting upper and lower bytes of (short int).
please look on my code it just return number 1 but must return 55 .
int number = 55;
int mynumber = 0;
//convert short int to char.
char upper = number >> 8;
char lower = number && 8;
//convert char to short int .
mynumber = (mynumber & 0xff00) | lower;
mynumber = (mynumber & 0x00ff) | (upper << 8);
printf("%i",mynumber);
The lower calculation is wrong:
char lower = number & 0xff;

Determining number of set bits in a char

This program is supposed to determine how many units are stored in the value of the variable c_val, if each unit is stored as a set bit.
My question is: why did the author write if (c % 2 == 1) count++; then shift c to the right with this statement c = c >> 1;?
#include <stdio.h>
#include <cstdlib>
int main(){
unsigned char c_val;
printf("char value = ");
scanf("%c", &c_val);
int count = 0;
unsigned char c = c_val;
while(c){
if (c % 2 == 1) count++;
c = c >> 1;
}
printf("%d bits are set", count);
system("pause");
}
The data size of type char is always one byte - no exceptions. This code, however, calculates the popcount - that is, the number of 1 bits - in c_val.
We can translate the relevant code from
while (c) {
if (c % 2 == 1) count++;
c = c >> 1;
}
to
while (c != 0) {
if (c & 0x1 == 1) count++; /* if the rightmost bit of c is 1, then count++ */
c = c / 2;
}
The last change I made works because right-shifting an unsigned integral data type (in this case, unsigned char) is equivalent to dividing by 2, with round-toward-zero semantics.
We can think of c as a conveyor belt of bits - zero bits come in from the left, and one bit falls off the right on each loop iteration. If the rightmost bit is a 1, we increase the count by 1, and otherwise the count remains unchanged. So, once c is filled with zero bits, we know that we have counted all the one bits, and exactly the one bits, so count contains the number of one bits in c_val.
This isn't a function to determine the "size" of instances of the type char at all, but rather to determine the number of bits in a character that are set to 1.
The expression
c % 2 == 1
determines whether or not the least significant bit is a 1.
The shifting brings the second to last bit into the last position so it can be tested.
The condition while (c) means to keep counting 1s and shifting until the whole byte is all zeros.
Your code is just coding how many 1 bits in char c. "c % 2 === 1" checks if the last bit in "c" is 1. So we must use "c = c >> 1" to shift the other bits in "c" to the last position.
Other way to do the same:
#include <stdio.h>
#include <conio.h>
unsigned int f (unsigned int a , unsigned int b);
unsigned int f (unsigned int a , unsigned int b)
{
return a ? f ( (a&b) << 1, a ^b) : b;
}
int bitcount(int n) {
int tot = 0;
int i;
for (i = 1; i <= n; i = i<<1)
if (n & i)
++tot;
return tot;
}
int bitcount_sparse_ones(int n) {
int tot = 0;
while (n) {
++tot;
n &= n - 1;
}
return tot;
}
int main()
{
int a = 12;
int b = 18;
int c = f(a,b);
printf("Sum = %d\n", c);
int CountA = bitcount(a);
int CountB = bitcount(b);
int CntA = bitcount_sparse_ones(a);
int CntB = bitcount_sparse_ones(b);
printf("CountA = %d and CountB = %d\n", CountA, CountB);
printf("CntA = %d and CntB = %d\n", CntA, CntB);
getch();
return 0;
}