C/C++ struct with bits fields packing in buffer - c++

I have defined my struct with bit fields.
typedef struct{
unsigned char primero;
unsigned int bit1: 1;
unsigned int bit2: 1;
unsigned char segundo;
unsigned char array[4];
unsigned int offset: 6;
} date;
I want to send this data by a socket in this specific orer of bits.
char auxsendbuf[BUF_SIZ];
memset(sendbuf, 0, BUF_SIZ);
date *st = (date *) auxsendbuf;
st->primero = 0x01;
st->bit1 = 1;
st->bit2 = 1;
st->segundo = 0x03;
st->array[0] = 0x04;
st->array[1] = 0x05;
st->array[2] = 0x06;
st->array[3] = 0x07;
My problem is that bit1 and bit2 are filled with 0s to complete a extra byte that i don't want to send. This is the result...
01 03 03 04 05 06 07 00 50
How can I force the order of bites? I can use C++ if it would necessary.

You need to group the fields so that the bitfields are together:
typedef struct{
unsigned char primero;
unsigned int bit1: 1;
unsigned int bit2: 1;
unsigned int offset: 6;
unsigned char segundo;
unsigned char array[4];
} date;
EDIT:
If you want all the bits to be packed the original order without padding, you need to make bit fields out of everything else in between:
typedef struct{
unsigned char primero;
unsigned int bit1: 1;
unsigned int bit2: 1;
unsigned char segundo: 8;
unsigned char array0: 8;
unsigned char array1: 8;
unsigned char array2: 8;
unsigned char array3: 8;
unsigned int offset: 6;
} date;
Note here that you can't have an array inside of a bitfield.
Why exactly do you need the bits in this order? Because any solution that uses it will be very convoluted.

Compiler can do weird things with your bit-fields. It's basically a "best-effort" approach, there is no standard way to influence it. In my experience, the best thing is to not use bit-fields for the purpose of "message-mapping". Declare the byte(s) you want to send and then do the bit-operations (setting and getting the bits you need) yourself.
Actually, since there could be issues with structure members' size, alignment and padding, and byte-ordering (for multi-byte data) to be perfectly safe, don't use structures either. Pack and unpack the message to an array of bytes yourself. Only in some application-specific optimizations and with some checks (using sizeof and ofsetoff tricks) should you use structures for message-mapping.

Related

Why is the size of the union greater than expected?

#include <iostream>
typedef union dbits {
double d;
struct {
unsigned int M1: 20;
unsigned int M2: 20;
unsigned int M3: 12;
unsigned int E: 11;
unsigned int s: 1;
};
};
int main(){
std::cout << "sizeof(dbits) = " << sizeof(dbits) << '\n';
}
output: sizeof(dbits) = 16, but if
typedef union dbits {
double d;
struct {
unsigned int M1: 12;
unsigned int M2: 20;
unsigned int M3: 20;
unsigned int E: 11;
unsigned int s: 1;
};
};
Output: sizeof(dbits) = 8
Why does the size of the union increase?
In the first and second union, the same number of bits in the bit fields in the structure, why the different size?
I would like to write like this:
typedef union dbits {
double d;
struct {
unsigned long long M: 52;
unsigned int E: 11;
unsigned int s: 1;
};
};
But, sizeof(dbits) = 16, but not 8, Why?
And how convenient it is to use bit fields in structures to parse bit in double?
members of a bit field will not cross boundaries of the specified storage type. So
unsigned int M1: 20;
unsigned int M2: 20;
will be 2 unsigned int using 20 out of 32 bit each.
In your second case 12 + 20 == 32 fits in a single unsigned int.
As for your last case members with different storage type can never share. So you get one unsigned long long and one unsigned int instead of a single unsigned long long as you desired.
You should use uint64_t so you get exact bit counts. unsigned int could e anything from 16 to 128 (or more) bit.
Note: bitfields are highly implementation defined, this is just the common way it usually works.

Size of structure - padding and alignment

I have an explicitly sized structure as follow:
typedef struct
{
unsigned long A : 4;
unsigned long B : 12;
union
{
unsigned long C1 : 8;
unsigned long C2 : 8;
unsigned long C3 : 8;
};
unsigned long D : 8;
}FooStruct;
The total size of this struct should be 32bit (4 bytes) in theory. However, I get a 12-byte size using sizeof so there should be some padding and alignment happening here.
I just don't see why and where. Can someone explain to me how this structure takes 12 bytes in memory?
The union forces the start of a new unsigned long, and the member after the union yet another unsigned long. Assuming long is 4 bytes that means your struct will have 3 unsigned longs for a total of 12 bytes. Although a union with three equally sized members also seems odd.
If you want this to have a size of 4 bytes why not change it to:
typedef struct
{
unsigned short A : 4;
unsigned short B : 12;
union
{
unsigned char C1 : 8;
unsigned char C2 : 8;
unsigned char C3 : 8;
};
unsigned char D : 8;
}FooStruct;
Additionally if you are using gcc and want to disable structure padding, you can use __attribute__((packed)):
struct FooStruct
{
unsigned long A : 4;
unsigned long B : 12;
union
{
unsigned long C1 : 8;
unsigned long C2 : 8;
unsigned long C3 : 8;
} __attribute__((packed)) C;
unsigned long D : 8;
} __attribute__((packed));
But beware that some architectures may have penalities on unalligned data access or not allow it at all.

How do I pass the function argument in arduino?

I'm trying to control velocity in a motor via writing register value in microcontroller.
unsigned long PrintHex32( uint32_t data) // prints 32-bit data in hex with leading zeroes
{
uint32_t data2 = data << 8;
char tmp[16];
uint16_t LSB = data2 & 0xffff;
uint16_t MSB = data2 >> 16;
unsigned long ppsval2 = sprintf(tmp, "0x%.4X%.4X%", MSB, LSB);
Serial.println(tmp);
Serial.println("***************");
return tmp;
}
void NoRamp() {
Serial.println("No Ramp");
unsigned long ppsVal = (VMAX * FS * uS);
unsigned long ppsVal3 = PrintHex32(ppsVal);
Serial.println(ppsVal);
Serial.println(ppsVal3);
Serial.println("$$$$$$");
//********* NO Ramp **********////////
sendData(0xA0, 0x00000000); //RAMP Mode
// sendData(0xA4, 0x03E80000); //VMAX-5rps/5hz
// sendData(0xA4, 0x00c80000);
sendData(0xA4, ppsVal3); //VMAX-1rps/1hz
}
at the end i need to be send data format after hex conversion sendData(0xA4, 0x00c80000)
but currently, I'm getting my print output:
No Ramp
0x00C80000
***************
51200
0
$$$$$$
umm where do I making the mistake? Can anyone kindly slam my head a bit please!
Thanks heaps!!
PS: also senddata method take below argument if anyone needs to know!
unsigned long sendData(unsigned long address, unsigned long datagram)
Edit:
I think I can understand the proper question to ask?
unsigned long PrintHex32( uint32_t data) // prints 32-bit data in hex with leading zeroes
{
uint32_t data2 = data << 8;
//char tmp[16];
uint16_t LSB = data2 & 0xffff;
uint16_t MSB = data2 >> 16;
unsigned long val = xxxx(uint16_t LSB) + uint16_t MSB(YYY);
//sprintf(tmp, "0x%.4X%.4X%", MSB, LSB);
return val ;
}
if you can see im converting my input data2 to hex using uint16_t LSB and uint16_t MSB. how do i save that two value as one single unsigned long val . then I can return the that varible.
I think using sprintf method is wrong as it does show just char representation?
please kindly correct me this if im wrong?
The xxxx in the edit should probably be 2^16 aka 65536:
#include <cassert>
using namespace std;
int main(int argc, char * argv[]) {
unsigned int data2 = 12345678;
uint16_t LSB = data2 & 0xffff;
uint16_t MSB = data2 >> 16;
unsigned long val = (1<<16) * MSB + LSB;
unsigned long val2 = 65536 * MSB + LSB;
assert(val == data2);
assert(val2 == data2);
}

Converting 4 bytes in little endian order into an unsigned integer

I have a string of 256*4 bytes of data. These 256* 4 bytes need to be converted into 256 unsigned integers. The order in which they come is little endian, i.e. the first four bytes in the string are the little endian representation of the first integer, the next 4 bytes are the little endian representation of the next integer, and so on.
What is the best way to parse through this data and merge these bytes into unsigned integers? I know I have to use bitshift operators but I don't know in what way.
Hope this helps you
unsigned int arr[256];
char ch[256*4] = "your string";
for(int i = 0,k=0;i<256*4;i+=4,k++)
{
arr[k] = ch[i]|ch[i+1]<<8|ch[i+2]<<16|ch[i+3]<<24;
}
Alternatively, we can use C/C++ casting to interpret a char buffer as an array of unsigned int. This can help get away with shifting and endianness dependency.
#include <stdio.h>
int main()
{
char buf[256*4] = "abcd";
unsigned int *p_int = ( unsigned int * )buf;
unsigned short idx = 0;
unsigned int val = 0;
for( idx = 0; idx < 256; idx++ )
{
val = *p_int++;
printf( "idx = %d, val = %d \n", idx, val );
}
}
This would print out 256 values, the first one is
idx = 0, val = 1684234849
(and all remaining numbers = 0).
As a side note, "abcd" converts to 1684234849 because it's run on X86 (Little Endian), in which "abcd" is 0x64636261 (with 'a' is 0x61, and 'd' is 0x64 - in Little Endian, the LSB is in the smallest address). So 0x64636261 = 1684234849.
Note also, if using C++, reinterpret_cast should be used in this case:
const char *p_buf = "abcd";
const unsigned int *p_int = reinterpret_cast< const unsigned int * >( p_buf );
If your host system is little-endian, just read along 4 bytes, shift properly and copy them to int
char bytes[4] = "....";
int i = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
If your host is big-endian, do the same and reverse the bytes in the int, or reverse it on-the-fly while copying with bit-shifting, i.e. just change the indexes of bytes[] from 0-3 to 3-0
But you shouldn't even do that just copy the whole char array to the int array if your PC is in little-endian
#define LEN 256
char bytes[LEN*4] = "blahblahblah";
unsigned int uint[LEN];
memcpy(uint, bytes, sizeof bytes);
That said, the best way is to avoid copying at all and use the same array for both types
union
{
char bytes[LEN*4];
unsigned int uint[LEN];
} myArrays;
// copy data to myArrays.bytes[], do something with those bytes if necessary
// after populating myArrays.bytes[], get the ints by myArrays.uint[i]

C++ Bits in 64 bit integer

Hello I have a struct here that is 7 bytes and I'd like to write it to a 64 bit integer. Next, I'd like to extract out this struct later from the 64 bit integer.
Any ideas on this?
#include "stdafx.h"
struct myStruct
{
unsigned char a;
unsigned char b;
unsigned char b;
unsigned int someNumber;
};
int _tmain(int argc, _TCHAR* argv[])
{
myStruct * m = new myStruct();
m->a = 11;
m->b = 8;
m->c = 12;
m->someNumber = 30;
printf("\n%s\t\t%i\t%i\t%i\t%i\n\n", "struct", m->a, m->b, m->c, m->someNumber);
unsigned long num = 0;
// todo: use bitwise operations from m into num (total of 7 bytes)
printf("%s\t\t%i\n\n", "ulong", num);
m = new myStruct();
// todo: use bitwise operations from num into m;
printf("%s\t\t%i\t%i\t%i\t%i\n\n", "struct", m->a, m->b, m->c, m->someNumber);
return 0;
}
You should to do something like this:
class structured_uint64
{
uint64_t data;
public:
structured_uint64(uint64_t x = 0):data(x) {}
operator uint64_t&() { return data; }
unsigned uint8_t low_byte(size_t n) const { return data >> (n * 8); }
void low_byte(size_t n, uint8_t val) {
uint64_t mask = static_cast<uint64_t>(0xff) << (8 * n);
data = (data & ~mask) | (static_cast<uint64_t>(val) << (8 * n));
}
unsigned uint32_t hi_word() const { return (data >> 24); }
// et cetera
};
(there is, of course, lots of room for variation on the details of the interface and where among the 64 bits the constituents are placed)
Using different types to alias the same portion of memory is a generally bad idea. The thing is, it's very valuable for the optimizer to be able to use reasoning like:
"Okay, I've read a uint64_t at the start of this block, and nowhere in the middle does the program write to any uint64_ts, therefore the value must be unchanged!"
which means it will get the wrong answer if you tried to change the value of the uint64_t object through a uint32_t reference. And as this is very dependent what optimizations are possible and done, it is actually pretty easy to never run across the problem in test cases, but see it in the real program you're trying to write -- and you'll spend forever trying to find the bug because you convinced yourself it's not this problem.
So, you really should do the insertion/extraction of the fields with bit twiddling (or intrinsics, if profiling shows that this is a performance issue and there are useful ones available) rather than trying to set up a clever struct.
If you really know what you're doing, you can make the aliasing work, I believe. But it should only be done if you really know what you're doing, and that includes knowing relevant rules from the standard inside and out (which I don't, and so I can't advise you on how to make it work). And even then you probably shouldn't do it.
Also, if you intend your integral types to be a specific size, you should really use the correct types. For example, never use unsigned int for an integer that is supposed to be exactly 32 bits. Instead use uint32_t. Not only is it self-documenting, but you won't run into a nasty surprise when you try to build your program in an environment where unsigned int is not 32 bits.
Use a union. Each element of a union occupies the same address space. The struct is one element, the unsigned long long is another.
#include <stdio.h>
union data
{
struct
{
unsigned char a;
unsigned char b;
unsigned char c;
unsigned int d;
} e;
unsigned long long f;
};
int main()
{
data dat;
dat.f = 0xFFFFFFFFFFFFFFFF;
dat.e.a = 1;
dat.e.b = 2;
dat.e.c = 3;
dat.e.d = 4;
printf("f=%016llX\n",dat.f);
printf("%02X %02X %02X %08X\n",dat.e.a,dat.e.b,dat.e.c,dat.e.d);
return 0;
}
Output, but note one byte of the original unsigned long long remains. Compilers like to align data such as 4-byte integers on addresses divisible by 4, so three bytes, then a pad byte so the integer is at offset 4 and the struct has a total size of 8.
f=00000004FF030201
01 02 03 00000004
This can be controlled in compiler-dependent fashion. Below is for Microsoft C++:
#include <stdio.h>
#pragma pack(push,1)
union data
{
struct
{
unsigned char a;
unsigned char b;
unsigned char c;
unsigned int d;
} e;
unsigned long long f;
};
#pragma pack(pop)
int main()
{
data dat;
dat.f = 0xFFFFFFFFFFFFFFFF;
dat.e.a = 1;
dat.e.b = 2;
dat.e.c = 3;
dat.e.d = 4;
printf("f=%016llX\n",dat.f);
printf("%02X %02X %02X %08X\n",dat.e.a,dat.e.b,dat.e.c,dat.e.d);
return 0;
}
Note the struct occupies seven bytes now and the highest byte of the unsigned long long is now unchanged:
f=FF00000004030201
01 02 03 00000004
Got it.
static unsigned long long compress(char a, char b, char c, unsigned int someNumber)
{
unsigned long long x = 0;
x = x | a;
x = x << 8;
x = x | b;
x = x << 8;
x = x | c;
x = x << 32;
x = x | someNumber;
return x;
}
myStruct * decompress(unsigned long long x)
{
printBinary(x);
myStruct * m = new myStruct();
m->someNumber = x | 4294967296;
x = x >> 32;
m->c = x | 256;
x = x >> 8;
m->b = x | 256;
x = x >> 8;
m->a = x | 256;
return m;
}