C++ class to access bytes/words of an unsigned integer - c++

union LowLevelNumber
{
unsigned int n;
struct
{
unsigned int lowByte : 8;
unsigned int highByte : 8;
unsigned int upperLowByte : 8;
unsigned int upperHighByte : 8;
} bytes;
struct
{
unsigned int lowWord : 16;
unsigned int highWord : 16;
} words;
};
This union allows me to access the unsigned integer byte or word-wise.
However, the code looks rather ugly:
var.words.lowWord = 0x66;
Is there a way which would allow me to write code like this:
var.lowWord = 0x66;
Update:
This is really about writing short / beautiful code as in the example above. The union solution itself does work, I just don't want to write .words or .bytes everytime I access lowWord or lowByte.

union LowLevelNumber {
unsigned int n;
struct {
unsigned int lowByte : 8;
unsigned int highByte : 8;
unsigned int upperLowByte : 8;
unsigned int upperHighByte : 8;
};
struct {
unsigned int lowWord : 16;
unsigned int highWord : 16;
};
};
Note the removed bytes and words names.

C++
Would http://www.cplusplus.com/reference/stl/bitset/ serve for your needs?
Plain C version would look something like this:
int32 foo;
//...
//Set to 0x66 at the low byte
foo &= 0xffffff00;
foo |= 0x66;
This is probably going to be more maintainable down the road than writing a custom class/union, because it follows the typical C idiom.

You can make
short& loword() { return (short&)(*(void*)&m_source); }
and use it if you don't care parenthesis.
Or you can go fancy
public class lowordaccess
{
unsigned int m_source;
public:
void assign(unsigned int& source) { m_source = source; }
short& operator=(short& value) { ... set m_source }
operator short() { return m_source & 0xFF; }
}
and then
struct LowLevelNumber
{
LowLevelNumber() { loword.assign(number); }
unsigned int number;
lowordaccess loword;
}
var.loword = 1;
short n = var.loword;
The latter technique is a known property emulation in C++.

You could easily wrap that in a class and use get/set accessors.

Using a union for this is bad, because it is not portable w.r.t. endianness.
Use accessor functions and implement them with bit masks and shifts.

Related

Is it possible to use a std::array as a data container for a POD struct?

I'm trying to update some legacy C code that uses an array as a data container with named access via macros to a more elegant C++17 solution (will be updated to C++20 when available, possible C++20 solutions are welcome). Sorry if there is a lot of code, but this is my first StackOverflow question suggestions regarding layout are welcome.
The current legacy C design:
#define WORD_ARR_SIZE 100
int16_t word_arr[WORD_ARR_SIZE]; //two byte variables
#define var0 word_arr[0] //macros are used to hide the array and use its members like variables
#define myValue word_arr[1]
#define myParameter word_arr[2]
#define free ((uint16_t)word_arr[3]) //'hidden' explicit cast needed when using the array as all data must be of the same type
#define var1 word_arr[4]
#define var2 word_arr[5]
#define var3 word_arr[6]
#define var4 word_arr[7]
#define var5 word_arr[7] //very easy to write the wrong index when adding new 'variables'
extern int send(int16_t* arr, size_t size); //The array is necessary as it needs to be fed to a library (code cannot be modified)
int main()
{
(uint16_t)var1 = UINT16_MAX; //'visible' explicit cast needed when using the array as all data is of the same type
myValues = 50;
for(int a = 20; a < 30; a++)
{
word_arr[a] = 10; //array is also used like it should be
}
return send(word_arr, WORD_ARR_SIZE);
}
My first attempt at solving the problem was using a struct instead of an array, this removed the explicit casts and the need for macros, but had the disadvantage of missing the simple access via index that the array implementation had, replacing it with an ugly reinterpret_cast.
//no need for pragma pack, the code doesn't care about padding
struct word_arr_t
{
int16_t var0; //no more macros
int16_t myValue;
int16_t myParameter;
uint16_t free; //no need for cast, value is alredy declared using the correct type
int16_t var1;
int16_t var2; //no way to get the index as if it was an array by simply using the value.
int16_t var3;
int16_t var4;
int16_t var5;
}word_arr;
constexpr size_t WORD_ARR_SIZE = sizeof(word_arr_t) / sizeof(uint16_t);
auto word_arr_p = reinterpret_cast<int16_t*>(&word_arr); //needed for indexed access
extern int send(int16_t* arr, size_t size);
int main()
{
word_arr.var1 = UINT16_MAX;
word_arr.myValues = 50;
for(int a = 20; a < 30; a++)
{
word_arr_p[a] = 10; //'hidden' pointer arithmetic to access the struct like an array
}
return send(word_arr_p, sizeof(word_arr_t));
}
The current solution:
I created a custom templated class called SmartStruct, I pass the struct type and values type in the template; I created an overload to operator[] allowing access via index hiding the ugly reinterpret_cast;
/**
* \brief A wrapper for structs made of object of the same type, allows indexed access
* \tparam StructT struct type
* \tparam DataT struct data type
*/
template <typename StructT, typename DataT>
class SmartStruct
{
DataT* m_dataPointer;
public:
/**
* \brief let the struct be accessible from the outside as well
*/
StructT Data;
const size_t Count;
/**
* \brief Default constructor
*/
SmartStruct();
/**
* \brief Construct by struct copy
* \param data struct to copy
*/
explicit SmartStruct(const StructT& data);
/**
* \brief operator to access struct in array style
* \param index element to access
* \return element, if index >= size then first element
*/
DataT& operator[](size_t index);
};
template <typename StructT, typename DataT>
SmartStruct<StructT, DataT>::SmartStruct() : Data{}, Count{ sizeof Data / sizeof(DataT) }
{
m_dataPointer = reinterpret_cast<DataT*>(&Data);
}
template <typename StructT, typename DataT>
SmartStruct<StructT, DataT>::SmartStruct(const StructT& data) : Count{ sizeof data / sizeof(DataT) }
{
//copy the struct
Data = data;
m_dataPointer = reinterpret_cast<DataT*>(&Data);
}
template <typename StructT, typename DataT>
DataT& SmartStruct<StructT, DataT>::operator[](size_t index)
{
if (index >= Count)
{
return *m_dataPointer;
}
return m_dataPointer[index];
}
Usage example:
struct word_arr_t
{
int16_t var0;
int16_t myValue;
int16_t myParameter;
uint16_t free;
int16_t var1;
int16_t var2;
int16_t var3; //Still no way to get array index from variable name
int16_t var4;
int16_t var5;
};
SmartStruct<word_arr_t, word> smart_word_arr{}; //Would love it if I could use std containers interface without having to implement it all by hand...
extern int send(int16_t* arr, size_t size);
int main()
{
word_arr_t& word_arr = smart_word_arr.Data;
word_arr.var1 = UINT16_MAX;
word_arr.myValues = 50;
for(int a = 20; a < 30; a++)
{
smart_word_arr[a] = 10;
}
return send(&smart_word_arr[0], smart_word_arr.Count);
}
Now that I got the context out of the way I can finally go to the real question:
Would it be possible to use a std::array as a a data container for the struct?
meaning initializing it via the struct; this would make it possible to access the data via variable using the struct itself and via index using std::array with the added bonus of a std interface without having to re-implement it.
My current attempt at getting this solution to work:
struct word_arr_t
{
int16_t var0;
int16_t myValue;
int16_t myParameter;
uint16_t free;
int16_t var1;
int16_t var2;
int16_t var3; //Still no way to get array index from variable name
int16_t var4;
int16_t var5;
}word_struct;
std:.array<int16_t, sizeof(word_arr_t) / sizeof(word)> word_array{};
//std:.array<int16_t, sizeof(word_arr_t) / sizeof(word)> word_array{&word_struct}; would be lovely if I could do this.
//word_array.Data = reinterpret_cast<int16_t*>(&word_struct); this would also be good.
extern int send(int16_t* arr, size_t size);
int main()
{
word_struct.var1 = UINT16_MAX;
word_struct.myValues = 50;
//copy struct into array, very very bad as it's not usable unless you know when
//code writes to the struct and when code writes to the array,
//this could be solved by wrapping the array into a read only object but still not ideal
//and extremely slow especially if the struct is very large
memcpy(word_array.Data, &word_struct, sizeof(word_struct));
for(auto& a : word_array)
{
a = 10;
}
return send(word_array.Data, word_array.Size);
}
If compiling this part of the code as C is an option, then the most elegant solution by far is to use a union. Since alignment isn't an issue here and there will be no padding. This can be done in C only, which allows type punning through unions.
typedef union
{
struct // C11 anonymous struct
{
int16_t var0;
int16_t myValue;
int16_t myParameter,
uint16_t free;
int16_t var1;
int16_t var2;
int16_t var3;
int16_t var4;
// var5 not declared on purpose
};
int16_t arr [WORD_ARR_SIZE];
} word_t;
This is how the original C code should have been written. Here all type information and special cases are handled at compile-time, and type punning from int16_t to uint16_t is well-defined and their effective types alias.
You can make an enum for the special case var5 indexing:
typedef enum
{
var0_index = 0,
myValue_index = 1,
myParameter_index = 2,
free_index = 3,
var_1index = 4,
var_2index = 5,
var_3index = 6,
var_4index = 7,
var_5index = 7,
} var_t;
word_t word =
{
// different sorts of designated initializers can be mixed:
.var0 = x,
.myValue = y,
[var5_index] = z,
};
("word" is a horrible type/variable name though, since in computer science the term word refers to a complete integer type. So please come up with something better.)
You cannot treat separate variable as array.
Not ideal but you can have accessors, something like:
struct word_arr_t
{
std::array<std::int16_t, 100> data{}; // your array
int16_t& var0() { return data[0]; }
int16_t& myValue() { return data[1]; }
int16_t& myParameter { return data[2]; }
uint16_t free() const { return static_cast<uint16_t>(data[3]); }
void set_free(uint16_t value) { data[3] = static_cast<int16_t>(value); }
int16_t& var1() { return data[4]; }
int16_t& var2() { return data[5]; }
int16_t& var3() { return data[6]; }
int16_t& var4() { return data[7]; }
int16_t& var5() { return data[8]; }
};
int main()
{
word_arr_t word_arr;
word_arr.var1() = INT16_MAX;
word_arr.myValues() = 50;
send(word_arr.data.data(), word_arr.data.size());
// ...
}
or enum indexes:
enum Index
{
var0,
myValue,
myParameter,
free,
var1,
var2,
var3,
var4,
var5,
};
struct word_arr_t
{
std::array<std::int16_t, 100> data{}; // your array
};
int main()
{
word_arr_t word_arr;
word_arr.data[Index::var1] = INT16_MAX;
word_arr.data[Index::myValues] = 50;
send(word_arr.data.data(), word_arr.data.size());
// ...
}
Would it be possible to use a std::array as a a data container for the struct?
A POD struct in C++ is a class that is trivial and has standard layout.
Starting with std::array as the underlying storage for a "struct" means you're not actually defining any struct with named members. You would have to write a class that contains the array and members that access indices of the array, and that can easily become not trivial and not standard layout.
By overloading operator[] you can access the "array" members of a struct with array-like syntax, while keeping the struct definition and POD status.
If it looks like a struct and []'s like a std::array, then it's probably good enough as far as the end-user is concerned.
Here is an example program demonstrating that:
#include <iostream>
#include <stdexcept>
#include <type_traits>
struct ArrPODStruct
{
int someHeaderValue1;
int someHeaderValue2;
int someHeaderValue3;
int a0;
int a1;
int a2;
int a3;
int a4;
int operator[] (int i)
{
switch (i)
{
case 0: return a0;
case 1: return a1;
case 2: return a2;
case 3: return a3;
case 4: return a4;
default: throw std::out_of_range("...");
}
}
};
int main()
{
ArrPODStruct arr;
// Put some useful data in arr...
std::cout << "Is POD: " << (std::is_pod<ArrPODStruct>() ? "Yes" : "No") << "\n";
std::cout << "Element 0: " << arr.a0 << " or " << arr[0] << "\n";
std::cout << "Element 1: " << arr.a1 << " or " << arr[1] << "\n";
std::cout << "Element 2: " << arr.a2 << " or " << arr[2] << "\n";
std::cout << "Element 3: " << arr.a3 << " or " << arr[3] << "\n";
std::cout << "Element 4: " << arr.a4 << " or " << arr[4] << "\n";
}
Output:
Is POD: Yes
Element 0: 0 or 0
Element 1: 0 or 0
Element 2: 0 or 0
Element 3: 0 or 0
Element 4: 0 or 0

C++ pass memory allocated / array by reference

SOLVED
I am writing a interface to an existing lib that handles struct bwords (see code below), and would like to offer the possibility to call some check functions on the bword itself, or on a string of bytes (a bword member) :
#include <cstdio>
typedef unsigned char byte;
typedef unsigned short ushort;
typedef struct bwordSt { ushort nbLetters; byte *L; } bword;
template<typename T, size_t N>
ushort checkBwL(T (&wL)[N], ushort wSz) {
return 0;
}
ushort checkBwL(const byte* const &wL, ushort wSz) {
return 0;
}
ushort checkBw(const bword &bw) {
return checkBwL(bw.L, bw.nbLetters);
}
int main() {
ushort n;
byte fL[2] = {0, 1};
n = checkBwL(fL, 2); // calls the template function
bword bW = {2, new byte[3]};
bW.L[0] = 0; bW.L[1] = 1; bW.L[2] = 2;
n = checkBwL(bW.L, 3); // calls the non-template function
n = checkBw(bW); // calls the non-template function
return n;
}
The string of bytes can be huge, so I'd like to pass by reference. And I did it.
The only way I found to offer a uniform interface was to duplicate the code of the base check function (checkBwL) in a template (for arrays[byte]) and an overload (for byte*), which is ugly and forces me to maintain two basically identical (big) functions.
Any way around this ?
SOLUTION
No need for the template function, just don't forget the const before the & in argument specification const byte* const &wL
The key to success is delegation:
#include <cstdio>
typedef unsigned char byte;
typedef unsigned short ushort;
typedef struct bwordSt { ushort nbLetters; byte *L; } bword;
ushort check_impl(ushort length, const byte* buffer)
{
// do your actual checking here
return 0;
}
template<typename T, size_t N>
auto checkBw(T (&wL)[N], ushort wSz) -> ushort
{
return wSz == (N * sizeof(T)) && // assuming no null terminator
check_impl(wSz, reinterpret_cast<const byte*>(wL));
}
ushort checkBw(const byte* const &wL, ushort wSz) {
return check_impl(wSz, wL);
}
ushort checkBw(const bword &bw) {
return check_impl(bw.nbLetters, bw.L);
}
int main() {
ushort n;
byte fL[2] = {0, 1};
n = checkBw(fL, 2); // calls the template function
bword bW = {2, new byte[3]};
bW.L[0] = 0; bW.L[1] = 1; bW.L[2] = 2;
n = checkBw(bW.L, 3); // calls the non-template function
n = checkBw(bW); // calls the non-template function
return n;
}

How I can cast an uint8 to a struct representing a byte?

I have a struct representing a byte having a fix offset 0b1111. I have defined a conversion operator to cast the SByte to unit8.
How can I have the opposite conversion (from uint8 to SByte)?
Is the only solution to replace the SByte with a uint8_t or maybe a union in the first place?
struct SByte
{
uint8_t offset : 4;
uint8_t bit4 : 1;
uint8_t bit5 : 1;
uint8_t bit6 : 1;
uint8_t bit7 : 1;
SByte():offset(15), bit4(0), bit5(0), bit6(0), bit7(0){}
explicit operator int8_t() const
{
return static_cast<uint8_t>((bit7 << 7) | (bit6 << 6) | (bit5 << 5) | (bit4 << 4));
}
};
int main()
{
auto lbyte = SByte();
auto result = static_cast<int8_t>(lbyte);
assert(result == 15); // 0b00001111
}
How can I have the opposite conversion (from uint8 to SByte)?
By defining a constructor:
explicit SByte(uint8_t byte) {
// extract individual bits from `byte`
}

Keil bit-fields allocates wrong size of union/struct

typedef union {
struct {
union {
struct {
unsigned int dev_t : 4; // Device Type, see DEV_type_t
unsigned int dev_n : 7; // Device Number
};
unsigned int id : 11; // CAN_ID
};
unsigned int online : 1;
unsigned int reserved : 4;
}; // 16 bit total
uint16_t _raw;
} CAN_prefix_t;
After compilation sizeof(CAN_prefix_t) shows 3 bytes, but expected to be 2 bytes (11+1+4 bits or 4+7+1+4 bits = 16 bits).
Could anyone advise how to define struct/union above in right way?
Thanks in advance!
This works for me (and for my project it's even better to have 2 "views" - from device and from CAN bus point of view):
#pragma pack(push,1)
typedef union {
struct {
unsigned int dev_n : 7;
unsigned int dev_t : 4;
unsigned int online : 1;
unsigned int reserved : 4;
} dev;
struct {
unsigned int id : 11;
unsigned int online : 1;
unsigned int reserved : 4;
} can;
uint16_t raw;
} CAN_prefix_t;
#pragma pack(pop)
IMPORTANT: Keil compiler allocates bit-fields in reverse order.
And also Keil poorly works with nested unions.

Reading bits performance

I'm writing a helper class which I intend to use for reading bits in reverse from a data block.
I tried doing an optimization where I used "rol" instructions for masking the data. However, to my surprise this is actually slower than creating a new bitmask during each access.
class reverse_bit_reader
{
public:
static const size_t bits_per_block = sizeof(unsigned long)*8;
static const size_t high_bit = 1 << (bits_per_block-1);
reverse_bit_reader(const void* data, size_t size)
: data_(reinterpret_cast<const unsigned long*>(data))
, index_(size-1)
{
// Bits are stored in left to right order, potentially ignore the last bits
size_t last_bit_index = index_ % bits_per_block;
bit_mask_ = high_bit >> (last_bit_index+1);
if(bit_mask_ == 0)
bit_mask_ = high_bit;
}
bool next_bit1()
{
return get_bit(index_--);
}
bool next_bit2() // Why is next_bit1 faster?
{
__asm // Rotate bit_mask.
{
mov eax, [ecx+0];
rol eax, 1;
mov [ecx+0], eax;
}
return data_[index_-- / bits_per_block] & bit_mask_;
}
bool eof() const{return index_ < 0;}
private:
bool get_bit(size_t index) const
{
const size_t block_index = index / bits_per_block;
const size_t bit_index = index % bits_per_block;
const size_t bit_mask = high_bit >> bit_index;
return data_[block_index] & bit_mask;
}
unsigned long bit_mask_;
int index_;
const unsigned long* data_;
};
Can anyone explain why next_bit1 is faster than next_bit2?
If you're going to be reading bits sequentially out of longs, starting from the most significant bit, and you want it to be as fast as possible, could you do something along these lines?
#define GETBIT ((theBit = (theLong < 0)), (theLong <<= 1), theBit)