Merging uint8 array into uint64 error - c

I am trying out this code where I first split a uint64 number into an array of uint8, followed by merging the said array back into the original number.
However when I attempt to print out the number out, it seems to return the max value of uint64.
uint8 buf[8];
uint64 test = 123456789012;
uint64 out = 0;
Uint64toUint8Arr(buf, test, 0);
out = Uint8ArrtoUint64(buf, 0);
std::cout << "out is " << out << std::endl;
where my functions are defined as:
void Uint64toUint8Arr (uint8* buf, uint64 var, uint32 lowest_pos)
{
buf[lowest_pos] = (var & 0x00000000000000FF) >> 0 ;
buf[lowest_pos+1] = (var & 0x000000000000FF00) >> 8 ;
buf[lowest_pos+2] = (var & 0x0000000000FF0000) >> 16 ;
buf[lowest_pos+3] = (var & 0x00000000FF000000) >> 24 ;
buf[lowest_pos+4] = (var & 0x000000FF00000000) >> 32 ;
buf[lowest_pos+5] = (var & 0x0000FF0000000000) >> 40 ;
buf[lowest_pos+6] = (var & 0x00FF000000000000) >> 48 ;
buf[lowest_pos+7] = (var & 0xFF00000000000000) >> 56 ;
}
uint64 Uint8ArrtoUint64 (uint8* var, uint32 lowest_pos)
{
return (var[lowest_pos+7] << 56) |
(var[lowest_pos+6] << 48) |
(var[lowest_pos+5] << 40) |
(var[lowest_pos+4] << 32) |
(var[lowest_pos+3] << 24) |
(var[lowest_pos+2] << 16) |
(var[lowest_pos+1] << 8) |
(var[lowest_pos] << 0);
}
My question is that did I go wrong in either the way I split or merge the uint64 number? I did a similar function for a uint32 type and it seemed to be ok.

The problem is that you're shifting uint8 in Uint8ArrtoUint64() function on more than 8 bits. As far as I know it's undefined behavior. Anyway, return value is uint8, so you're "or'ing" eight times eight uint8 numbers and finally you have only uint8 number, not uint64! You need to cast them to uint64 first, then shift.
uint64 Uint8ArrtoUint64 (uint8* var, uint32 lowest_pos)
{
return (((uint64)var[lowest_pos+7]) << 56) |
(((uint64)var[lowest_pos+6]) << 48) |
(((uint64)var[lowest_pos+5]) << 40) |
(((uint64)var[lowest_pos+4]) << 32) |
(((uint64)var[lowest_pos+3]) << 24) |
(((uint64)var[lowest_pos+2]) << 16) |
(((uint64)var[lowest_pos+1]) << 8) |
(((uint64)var[lowest_pos]) << 0);
}
Note: As #interjay noted, shifting operation on uint8 will actually give us uint32. I'm not sure about that, but anyway it's better to mention it.

Related

Converting data back to its original items

I have some code and I don't understand how to get the individual items back:
u32_t foo = ((u32_t)((d) & 0xff) << 24) | ((u32_t)((c) & 0xff) << 16) |
((u32_t)((b) & 0xff) << 8) | (u32_t)((a) & 0xff)
I would like to input the result of this conversion
I want this to convert a IP address back to its parts to display.
But when I enter 192 168 1 200 I get 0xC801A8C0 and I don't get it converted back.
Does anyone know how I can items in a union struct?
I try to use LwIP but have problems with union structs. I try to access local_ip and remote_ip.
u32_t d = (foo >> 24) & 0xFF; // Get the bits 32nd...25th
u32_t c = (foo >> 16) & 0xFF; // 24th...17th
u32_t b = (foo >> 8) & 0xFF; // 16th...9th
u32_t a = (foo) & 0xFF; // 8th...1st
This is actually doing the opposite of the code above.
You can mask out the values inside foo
u32_t thisWasD = (foo & 0xff000000) >> 24; // ==> will null out the lowest 24 bits
u32_t thisWasC = (foo & 0x00ff0000) >> 16; // ==> will null out the upper 8 and lowest 16 bit
u32_t thisWasB = (foo & 0x0000ff00) >> 8; // ==> etc
u32_t thisWasA = (foo & 0xff) // etc - no shift needed
and shift them back so they are alignt in fist 8 bit ( by 24,16,8 - last one is already ok
it's like you have one int input and you want to divide into bytes by bytes & store each bytes in seperate integers
int main() {
a = ((uint32_t)((foo) & 0x000000ff) << 24);
b = ((uint32_t)((foo) & 0x0000ff00) << 16);
c = ((uint32_t)((foo) & 0x00ff0000) << 8);
d = ((uint32_t)((foo) & 0xff000000);
}

Overflow while shiffting C [duplicate]

I am new to bits, I am trying to get 64 bit value send using UDP.
int plugin(unsigned char *Buffer) {
static const uint8_t max_byte = 0xFF;
uint8_t id[8];
id[0] = (uint8_t)((Buffer[0]) & max_byte);
id[1] = (uint8_t)((Buffer[1] >> 8) & max_byte);
id[2] = (uint8_t)((Buffer[2] >> 16) & max_byte);
id[3] = (uint8_t)((Buffer[3] >> 24) & max_byte);
id[4] = (uint8_t)((Buffer[4] >> 32) & max_byte);
id[5] = (uint8_t)((Buffer[5] >> 40) & max_byte);
id[6] = (uint8_t)((Buffer[6] >> 48) & max_byte);
id[7] = (uint8_t)((Buffer[7] >> 56) & max_byte);
}
I am getting error right shift count >= width of type. I tried other way aswell
int plugin(unsigned char *Buffer) {
uint64_t id = (Buffer[0] | Buffer[1] << 8 | Buffer[2] << 16 | Buffer[3] << 24 | Buffer[4] < 32 | Buffer[5] << 40 | Buffer[6] << 48 | Buffer[7] << 56);
printf("ID %" PRIu64 "\n", id);
}
Its getting error left shift count >= width of type
I checked the system it is x86_64. Could someone please tell me the reason why its happening? Please suggest me a way forward.
This happens because of default integer promotion, basically.
When you do this:
uint64_t id = Buffer[7] << 56;
That Buffer[7] is an unsigned char, but it gets promoted to int in the arithmetic expression, and your int is not 64 bits. The type of the left hand side does not automatically "infect" the right hand side, that's just not how C works.
You need to cast:
const uint64_t id = ((uint64_t) Buffer[7]) << 56;
and so on.

right shift count >= width of type or left shift count >= width of type

I am new to bits, I am trying to get 64 bit value send using UDP.
int plugin(unsigned char *Buffer) {
static const uint8_t max_byte = 0xFF;
uint8_t id[8];
id[0] = (uint8_t)((Buffer[0]) & max_byte);
id[1] = (uint8_t)((Buffer[1] >> 8) & max_byte);
id[2] = (uint8_t)((Buffer[2] >> 16) & max_byte);
id[3] = (uint8_t)((Buffer[3] >> 24) & max_byte);
id[4] = (uint8_t)((Buffer[4] >> 32) & max_byte);
id[5] = (uint8_t)((Buffer[5] >> 40) & max_byte);
id[6] = (uint8_t)((Buffer[6] >> 48) & max_byte);
id[7] = (uint8_t)((Buffer[7] >> 56) & max_byte);
}
I am getting error right shift count >= width of type. I tried other way aswell
int plugin(unsigned char *Buffer) {
uint64_t id = (Buffer[0] | Buffer[1] << 8 | Buffer[2] << 16 | Buffer[3] << 24 | Buffer[4] < 32 | Buffer[5] << 40 | Buffer[6] << 48 | Buffer[7] << 56);
printf("ID %" PRIu64 "\n", id);
}
Its getting error left shift count >= width of type
I checked the system it is x86_64. Could someone please tell me the reason why its happening? Please suggest me a way forward.
This happens because of default integer promotion, basically.
When you do this:
uint64_t id = Buffer[7] << 56;
That Buffer[7] is an unsigned char, but it gets promoted to int in the arithmetic expression, and your int is not 64 bits. The type of the left hand side does not automatically "infect" the right hand side, that's just not how C works.
You need to cast:
const uint64_t id = ((uint64_t) Buffer[7]) << 56;
and so on.

unknown parse error when testing function

I have the function below which seems to act as it should, however when running the program through a testing program, I am given the errors: parse error: [int xSwapped = ((255 << nShift) | (255 << mShift));] and
undeclared variable `xSwapped': [return (~xSwapped & x) | nMask | mMask;]
int dl15(int x, int n, int m){
// calculates shifts, create mask to shift, combine result
// get number of bytes needed to shift, multiplying by 8
// get Masks by shifting 0xff and shift amount
// shift bits to required position
// combine results
int nShift = n<< 3;
int mShift = m<< 3;
int nMask = x & (255 << nShift);
int mMask = x & (255 << mShift);
nMask = 255 & (nMask >> nShift);
mMask = 255 & (mMask >> mShift);
nMask = nMask << mShift;
mMask = mMask << nShift;
int xSwapped = ((255 << nShift) | (255 << mShift));
return (~xSwapped & x) | nMask | mMask;
}
Not certain what im missing, thank you.
It looks like you are using a C compiler set to an old C standard. Prior to C99 you could not put executable statements before declarations.
You can fix this by moving the declaration of xSwapped to the top:
int nShift = n<< 3;
int mShift = m<< 3;
int nMask = x & (255 << nShift);
int mMask = x & (255 << mShift);
int xSwapped; // Declaration
nMask = 255 & (nMask >> nShift);
mMask = 255 & (mMask >> mShift);
nMask = nMask << mShift;
mMask = mMask << nShift;
xSwapped = ((255 << nShift) | (255 << mShift)); // Assignment
return (~xSwapped & x) | nMask | mMask;

Mismatch when converting an char array into ULLs and vice versa in C

I have a huge 2048-bit string (string 'encrypted' of length 256 in example) it can take random values meaning NOT necessary ASCII values.
My goal is to chunk it into unsigned long long (ULL) values to be used for some custom operation (which operates only on ULL) and restore back the original string from the chunked ULLs. (My computer is little endian and 64-bit)
I have the following code where my goal is to make encrypted2 match encrypted. However the below code is incorrect. I think it messes with endian-ness and so I do not get back the original string contents. Can anyone help me fix the issue or suggest a good work around?
unsigned long long val, longInt;
char buffer[9];
buffer[8] = '\0';
char byteArray[9];
byteArray[8] = '\0';
for(chunk = 0; chunk < 32; chunk++) {
strncpy(buffer, encrypted + 8 * chunk, 8);
val = (uint64_t)buffer[0] << 56 |
(uint64_t)buffer[1] << 48 |
(uint64_t)buffer[2] << 40 |
(uint64_t)buffer[3] << 32 |
(uint64_t)buffer[4] << 24 |
(uint64_t)buffer[5] << 16 |
(uint64_t)buffer[6] << 8 |
(uint64_t)buffer[7];
vals[chunk] = val;
}
for (chunk = 0; chunk < 32; chunk++) {
longInt = vals[chunk];
byteArray[0] = (char)((longInt >> 56) & 0xFF);
byteArray[1] = (char)((longInt >> 48) & 0xFF);
byteArray[2] = (char)((longInt >> 40) & 0xFF);
byteArray[3] = (char)((longInt >> 32) & 0xFF);
byteArray[4] = (char)((longInt >> 24) & 0xFF);
byteArray[5] = (char)((longInt >> 16) & 0xFF);
byteArray[6] = (char)((longInt >> 8) & 0xFF);
byteArray[7] = (char)((longInt) & 0xFF);
strncpy(encrypted2 + chunk * 8, byteArray, 8);
}
Please help me match encrypted and encrypted2 in my above code.
Example input for encrypted[256] would be
C���EK�U�ߺA#|��-��fDJ�J
ڰ���.�2(��+<��^���r0��v�.�'��GR�M��,52�����{r7RPqRD1�ú
��q4�iP��E�Cm��$
���Z�+�Q��&Xx�F0� X#(���N���6r�R�`�]"gvV2[)��75��)
While you're working with char arrays, you're not working with strings: you should be using memcpy rather than strncpy.

Resources