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.
Related
I do not know how to put an appropriate title to explain the problem. Thus feel free if you have a more informative title to edit.
To understand the problem, let me explain what I am doing.
I have created a structure as following:
typedef union __attribute__ ((__packed__)) adcs_measurements_t
{
unsigned char raw[72];
struct __attribute__ ((__packed__)) //191
{
int magneticFieldX : 16;
int magneticFieldY : 16;
int magneticFieldZ : 16;
int coarseSunX : 16;
int coarseSunY : 16;
int coarseSunZ : 16;
int sunX : 16;
int sunY : 16;
int sunZ : 16;
int nadirX : 16;
int nadirY : 16;
int nadirZ : 16;
int XAngularRate : 16;
int YAngularRate : 16;
int ZAngularRate : 16;
int XWheelSpeed : 16;
int YWheelSpeed : 16;
int ZWheelSpeed : 16;
int star1BX : 16;
int star1BY : 16;
int star1BZ : 16;
int star1OX : 16;
int star1OY : 16;
int star1OZ : 16;
int star2BX : 16;
int star2BY : 16;
int star2BZ : 16;
int star2OX : 16;
int star2OY : 16;
int star2OZ : 16;
int star3BX : 16;
int star3BY : 16;
int star3BZ : 16;
int star3OX : 16;
int star3OY : 16;
int star3OZ : 16;
} fields;
} adcs_measurements_t;
I populate the structure by calling a function as following:
void adcsTM191_measurements(adcs_measurements_t* dataOut)
{
int pass;
unsigned char TMID = 191;
unsigned char readBuff[72] = {0};
pass = I2C_write(ADCS_ADDR, &TMID, 1);
if(pass != 0)
{
printf("write error %d\n", pass);
}
pass = I2C_read(ADCS_ADDR, readBuff, 72);
if(pass != 0)
{
printf("read error %d\n", pass);
}
dataOut->fields.magneticFieldX = (readBuff[1] & 0x00FF) << 8 | (readBuff[0] & 0x00FF);
dataOut->fields.magneticFieldY = (readBuff[3] & 0x00FF) << 8 | (readBuff[2] & 0x00FF);
dataOut->fields.magneticFieldZ = (readBuff[5] & 0x00FF) << 8 | (readBuff[4] & 0x00FF);
dataOut->fields.coarseSunX = (readBuff[7] & 0x00FF) << 8 | (readBuff[6] & 0x00FF);
dataOut->fields.coarseSunY = (readBuff[9] & 0x00FF) << 8 | (readBuff[8] & 0x00FF);
dataOut->fields.coarseSunZ = (readBuff[11] & 0x00FF) << 8 | (readBuff[10] & 0x00FF);
dataOut->fields.sunX = (readBuff[13] & 0x00FF) << 8 | (readBuff[12] & 0x00FF);
dataOut->fields.sunY = (readBuff[15] & 0x00FF) << 8 | (readBuff[14] & 0x00FF);
dataOut->fields.sunZ = (readBuff[17] & 0x00FF) << 8 | (readBuff[16] & 0x00FF);
dataOut->fields.nadirX = (readBuff[19] & 0x00FF) << 8 | (readBuff[18] & 0x00FF);
dataOut->fields.nadirY = (readBuff[21] & 0x00FF) << 8 | (readBuff[20] & 0x00FF);
dataOut->fields.nadirZ = (readBuff[23] & 0x00FF) << 8 | (readBuff[22] & 0x00FF);
dataOut->fields.XAngularRate = (readBuff[25] & 0x00FF) << 8 | (readBuff[24] & 0x00FF);
dataOut->fields.YAngularRate = (readBuff[27] & 0x00FF) << 8 | (readBuff[26] & 0x00FF);
dataOut->fields.ZAngularRate = (readBuff[29] & 0x00FF) << 8 | (readBuff[28] & 0x00FF);
dataOut->fields.XWheelSpeed = (readBuff[31] & 0x00FF) << 8 | (readBuff[30] & 0x00FF);
dataOut->fields.YWheelSpeed = (readBuff[33] & 0x00FF) << 8 | (readBuff[32] & 0x00FF);
dataOut->fields.ZWheelSpeed = (readBuff[35] & 0x00FF) << 8 | (readBuff[34] & 0x00FF);
dataOut->fields.star1BX = (readBuff[37] & 0x00FF) << 8 | (readBuff[36] & 0x00FF);
dataOut->fields.star1BY = (readBuff[39] & 0x00FF) << 8 | (readBuff[38] & 0x00FF);
dataOut->fields.star1BZ = (readBuff[41] & 0x00FF) << 8 | (readBuff[40] & 0x00FF);
dataOut->fields.star1OX = (readBuff[43] & 0x00FF) << 8 | (readBuff[42] & 0x00FF);
dataOut->fields.star1OY = (readBuff[45] & 0x00FF) << 8 | (readBuff[44] & 0x00FF);
dataOut->fields.star1OZ = (readBuff[47] & 0x00FF) << 8 | (readBuff[46] & 0x00FF);
dataOut->fields.star2BX = (readBuff[49] & 0x00FF) << 8 | (readBuff[48] & 0x00FF);
dataOut->fields.star2BY = (readBuff[51] & 0x00FF) << 8 | (readBuff[50] & 0x00FF);
dataOut->fields.star2BZ = (readBuff[53] & 0x00FF) << 8 | (readBuff[52] & 0x00FF);
dataOut->fields.star2OX = (readBuff[55] & 0x00FF) << 8 | (readBuff[54] & 0x00FF);
dataOut->fields.star2OY = (readBuff[57] & 0x00FF) << 8 | (readBuff[56] & 0x00FF);
dataOut->fields.star2OZ = (readBuff[59] & 0x00FF) << 8 | (readBuff[58] & 0x00FF);
dataOut->fields.star3BX = (readBuff[61] & 0x00FF) << 8 | (readBuff[60] & 0x00FF);
dataOut->fields.star3BY = (readBuff[63] & 0x00FF) << 8 | (readBuff[62] & 0x00FF);
dataOut->fields.star3BZ = (readBuff[65] & 0x00FF) << 8 | (readBuff[64] & 0x00FF);
dataOut->fields.star3OX = (readBuff[67] & 0x00FF) << 8 | (readBuff[66] & 0x00FF);
dataOut->fields.star3OY = (readBuff[69] & 0x00FF) << 8 | (readBuff[68] & 0x00FF);
dataOut->fields.star3OZ = (readBuff[71] & 0x00FF) << 8 | (readBuff[70] & 0x00FF);
}
Finally I print, for instance YWheelSpeed.
adcsTM191_measurements(&temp);
printf("structure y wheel speed is: %d \n", temp.fields.YWheelSpeed);
This value should print a negative value and it does:
structure y wheel speed is: -97
Now here is the thing, if I print (readBuff[27] & 0x00FF) << 8 | (readBuff[26] & 0x00FF), which corresponds to what was populated inside the Y wheel speed variable, anywhere inside adcsTM191_measurements(adcs_measurements_t* dataOut) it does not print this negative value. Rather it prints the maximum value of an unsigned char (65,535).
int y = (int) (readBuff[33] & 0x00FF) << 8 | (readBuff[32] & 0x00FF);
printf("inside struct y is: %d", y);
I am expecting that storing inside the structure does a kind of implicit cast and so it prints the negative value as expected. How is it doing it? How can I print the correct value without the use of the structure?
According to C 2018 footnote 128, it is implementation-defined whether a bit-field defined with int, as in int YWheelSpeed is signed or unsigned. Since your implementation is showing a negative value for it, presumably it is signed, and therefore, as a 16-bit signed integer, it can represent values from −32,768 to 32,767.
We can also deduce that int in your implementation is more than 16 bits, likely 32 bits (from the fact that “65535” is printed in one case when int y is printed with “%d”).
Consider this assignment:
dataOut->fields.YWheelSpeed = (readBuff[33] & 0x00FF) << 8 | (readBuff[32] & 0x00FF);`
In this expression, readBuff[33] and readBuff[32] are converted to int by the usual promotions. 0x00FF is also an int.
If we suppose readBuff[33] is 255 and readBufff[32] is 159 (which is 28−97), then the value of the expression on the right side of the = is 65,439 (which is 216−97). In an assignment, the right operand is converted to the type of the left operand, which is a 16-bit signed integer. In this case, the value, 65,439, cannot be represented in a 16-bit signed integer. C 2018 6.3.1.3 3 tells us “either the result is implementation-defined or an implementation-defined signal is raised.”
A common implementation of this conversion is to produce the result modulo 216 or, equivalently, to reinterpret the 16 low bits of the int as a two’s complement 16-bit integer. This produces −97. Since your implementation subsequently showed −97 for the value, presumably this is what your implementation did.
Thus, dataOut->fields.YWheelSpeed is assigned the value −97. When it is later printed with:
printf("structure y wheel speed is: %d \n", temp.fields.YWheelSpeed);
then the default argument promotions, which include the usual integer promotions, convert temp.fields.YWheelSpeed from a signed 16-bit integer with value −97 to an int with value −97, and “-97” is printed.
In contrast, suppose (readBuff[33] & 0x00FF) << 8 | (readBuff[32] & 0x00FF) is printed with %d. As we saw above, the value of this expression is 65,439, so “65439” should be printed.
The question states:
Now here is the thing, if I print (readBuff[27] & 0x00FF) << 8 | (readBuff[26] & 0x00FF), which corresponds to what was populated inside the Y wheel speed variable,… it prints the maximum value of an unsigned char (65,535).
However, (readBuff[27] & 0x00FF) << 8 | (readBuff[26] & 0x00FF) is not the value that was assigned to YWheelSpeed, which is presumably the “Y wheel speed variable”. YWheelSpeed was assigned from readBuff elements 32 and 33, not 26 and 27. Thus we should not be surprised that some different value is printed rather than 65,439.
You probably have 32-bit int, so the initialization never sets the sign bit. But the structure field is only 16 bits, and will be sign-extended when it's converted to int for the printf() call.
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);
}
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.
I'm working in C, and assume I have 2 bytes in little endian:
buffer[0] = 0x01; buffer[1] = 0x02;
How can I convert the above into a combined 12 bit number? So after combining it should look like:
0x0201
This is a 16 bit number. each byte is 8 bits.
int i = (buffer[0] & 0xFF) | (buffer[1] << 8);
If you want 12 bits then this
int i = (buffer[0] & 0xFF) | ((buffer[1] & 0x0F) << 8);
Convert back to buffer
char buffer[2];
buffer[0] = i & 0xFF;
buffer[1] = (i >> 8) & 0x0F;
3 bytes (24 bits) number:
number = ((buffer[2] & 0x0F) << 16) | ((buffer[1] & 0x0F) << 8) | buffer[0];
2 bytes (16 bits) number:
number = ((buffer[2] & 0x0F) << 8) | ((buffer[1] & 0x0F) << 4) | buffer[0];
In case buffer[] is a signed type use
int twelve_bit1 = ((buffer[1] & 0xF) << 8) | (buffer[0] & 0xFF);
or
int twelve_bit2 = ((buffer[1] & 0xF) << 8) | (unsigned char) buffer[0];
or
int twelve_bit3 = ((buffer[1] & 15) * 256) | buffer[0] & 255;
All generate similar code.
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.