C++ 任何位长字节对齐缓冲区的位对齐访问
对于嵌入式系统(little Endian ARM,语言C——即使我在这里使用C++进行测试),我编写了附带的代码。我必须发送和接收不同配置的数据,位对齐,并且具有给定的位长度。对于我必须发送/接收的每个变量,使用字段_conf_t执行配置,如:C++ 任何位长字节对齐缓冲区的位对齐访问,c++,c,C++,C,对于嵌入式系统(little Endian ARM,语言C——即使我在这里使用C++进行测试),我编写了附带的代码。我必须发送和接收不同配置的数据,位对齐,并且具有给定的位长度。对于我必须发送/接收的每个变量,使用字段_conf_t执行配置,如: typedef struct field_conf_t { ... }; // see below typedef struct { field_conf_t a; field_conf_t b; field_co
typedef struct field_conf_t { ... }; // see below
typedef struct {
field_conf_t a;
field_conf_t b;
field_conf_t c;
} tx_fields_conf_t;
const tx_fields_conf_t tx_fields_conf = {
{ 0, 8 }, // a - offset/length
{ 28, 12 }, // b - offset/length
{ 56, 8 } // c - offset/length
};
我的问题是,我考虑了很多关于单位操作的问题,测试失败了
代码如下:
#include <stdint.h>
#define BOOST_TEST_MODULE BitFieldTest
#include <boost/test/unit_test.hpp>
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef unsigned long long uint64;
typedef struct {
uint8 offset; // [0-63]
uint8 length; // [1-32]
} field_conf_t;
typedef struct {
field_conf_t a;
field_conf_t b;
field_conf_t c;
} tx_fields_conf_t;
typedef union {
uint8 buf[8];
uint64 contents;
} msg_t;
void set_value(msg_t* const msg, const field_conf_t* const field, uint32 value)
{
const uint32 mask = (1 << field->length) - 1;
msg->contents &= ~(mask << field->offset); // clear old contens
msg->contents |= (value & mask) << field->offset; // set new contens
}
uint32 get_value(const msg_t* const msg, const field_conf_t* const field)
{
const uint32 mask = (1 << field->length) - 1;
uint64 value = (msg->contents >> field->offset);
value &= mask;
return (uint32)value;
}
// ########################################################################
struct TestFixture {
TestFixture() : a(0xAA), b(0xBBB), c(0xCC) {
conf.a.offset = 0; conf.a.length = 8;
conf.b.offset = 25; conf.b.length = 12;
conf.c.offset = 56; conf.a.length = 8;
}
uint32 a, b, c;
msg_t msg;
tx_fields_conf_t conf;
};
BOOST_FIXTURE_TEST_SUITE(MsgBitfieldTest, TestFixture);
BOOST_AUTO_TEST_CASE(Test_01)
{
set_value(&msg, &conf.a, a);
BOOST_CHECK(get_value(&msg, &conf.a) == a);
set_value(&msg, &conf.b, b);
BOOST_CHECK(get_value(&msg, &conf.a) == a);
BOOST_CHECK(get_value(&msg, &conf.b) == b);
set_value(&msg, &conf.c, c);
BOOST_CHECK(get_value(&msg, &conf.a) == a);
BOOST_CHECK(get_value(&msg, &conf.b) == b);
BOOST_CHECK(get_value(&msg, &conf.c) == c);
}
BOOST_AUTO_TEST_SUITE_END();
缓冲区大小始终为8字节;我很高兴我可以在这里使用64位长;在此之前,字节对齐操作也失败(每个字节上的掩码和位操作)。请注意,该值不能大于int32/uint32。我还知道C位字段。他们太慢了,我需要一个用于嵌入式系统的快速解决方案(还有其他耗时的任务)
我还对使用lsb/msb 32位甚至8字节片快速解决方案感兴趣,但我认为由于编译器的原因,64位数据类型的使用性能更高。在第一个代码块中,您有以下问题:
const tx_fields_conf_t tx_fields_conf = {
{ 0, 8 }, // a - offset/length
{ 28, 12 }, // b - offset/length -- note the 28 here as the offset
{ 56, 8 } // c - offset/length
};
struct TestFixture {
TestFixture() : a(0xAA), b(0xBBB), c(0xCC) {
conf.a.offset = 0; conf.a.length = 8;
conf.b.offset = 25; conf.b.length = 12; // offset is *25* here, not 28 as above. Poss. problem?
conf.c.offset = 56; conf.a.length = 8;
}
uint32 a, b, c;
msg_t msg;
tx_fields_conf_t conf;
};
但在以后的应用程序中,您有:
const tx_fields_conf_t tx_fields_conf = {
{ 0, 8 }, // a - offset/length
{ 28, 12 }, // b - offset/length -- note the 28 here as the offset
{ 56, 8 } // c - offset/length
};
struct TestFixture {
TestFixture() : a(0xAA), b(0xBBB), c(0xCC) {
conf.a.offset = 0; conf.a.length = 8;
conf.b.offset = 25; conf.b.length = 12; // offset is *25* here, not 28 as above. Poss. problem?
conf.c.offset = 56; conf.a.length = 8;
}
uint32 a, b, c;
msg_t msg;
tx_fields_conf_t conf;
};
有没有可能这是一个重要的差异?也许什么都没有,但我确实注意到了……我想我应该指出它。问题是在
设置值中
const uint32 mask = (1 << field->length) - 1;
msg->contents &= ~(mask << field->offset); // clear old contens
msg->contents |= (value & mask) << field->offset; // set new contens
谢谢你指出这一点,但这并不重要。我喜欢在最终版本中使用的结构“API”。