具有匿名结构的不同位映射
Different bit mappings with anonymous structs
我想为一些位实现不同的映射。
我想出了这个对我来说相当有效的解决方案:
union myBits{
// constructors
struct{ // Mapping 1
uint16_t a : 8, b : 8;
};
struct{ // Mapping 2
uint16_t c : 10, d : 6;
};
};
然后我可以通过
访问不同的位映射
myBits mb(/**/);
mb.c = 10;
mb.a = 2;
我认为这个功能非常优雅,虽然它不被认为是标准的 C++。
g++ 和 clang 产生警告(告诉我匿名结构在标准中不被明确允许),Visual Studio 编译代码而不产生任何警告。
我的问题是:是否有一种现代 C++1x 方法可以编写具有相同功能的相同代码,而不仅仅是命名结构?
由于 C++ 与 C 相比的限制,我看不到在标准 C++ 中执行此操作的任何有效、合法和优雅的方法。您只能选择三个属性中的两个:)
高效合法,但不够优雅
struct myBits
{
void set_bits(size_t start_bit, size_t end_bit, uint16_t value)
{
size_t len = end_bit - start_bit + 1;
uint16_t mask = ((1 << len) - 1) << (start_bit - 1);
word = (word & ~mask) | ((value << (start_bit - 1)) & mask);
}
uint16_t get_bits(size_t start_bit, size_t end_bit)
{
size_t len = end_bit - start_bit + 1;
return (word >> (start_bit - 1)) & ((1 << len) - 1);
}
uint16_t word;
};
在您的场景中使用它:
myBits mb;
mb.set_bits(1, 10, 10);
mb.set_bits(1, 8, 2);
这可能真的不如问题中的代码有效,这实际上取决于编译器如何生成用于访问位域的代码与上面的代码。与初始解决方案相比,这样做的好处是您可以访问任何位子集,而无需为其定义新的结构和位域。
合法优雅,但效率不高
template<size_t start_bit, size_t end_bit>
struct bit_field
{
bit_field(uint16_t& w) : word(w) {}
operator uint16_t() const
{
return (word >> (start_bit - 1)) & ((1 << len) - 1);
}
bit_field& operator=(uint16_t value)
{
uint16_t mask = ((1 << len) - 1) << (start_bit - 1);
word = (word & ~mask) | ((value << (start_bit - 1)) & mask);
return *this;
}
const size_t len = end_bit - start_bit + 1;
uint16_t &word;
};
struct Word
{
Word(uint16_t w) : word(w), a(word), b(word), c(word), d(word) {}
uint16_t word;
bit_field<1, 8> a;
bit_field<9, 16> b;
bit_field<1, 10> c;
bit_field<11, 16> d;
};
这种情况下的用法与您的示例一样优雅:
Word w(0);
w.c = 10;
w.a = 2;
这种方法的问题在于它确实 space 效率低下。与仅存储位的初始方法相比,您必须为每个位字段声明一个结构。
高效优雅,但不合法
这基本上就是您在问题中描述的方式。
我想为一些位实现不同的映射。 我想出了这个对我来说相当有效的解决方案:
union myBits{
// constructors
struct{ // Mapping 1
uint16_t a : 8, b : 8;
};
struct{ // Mapping 2
uint16_t c : 10, d : 6;
};
};
然后我可以通过
访问不同的位映射myBits mb(/**/);
mb.c = 10;
mb.a = 2;
我认为这个功能非常优雅,虽然它不被认为是标准的 C++。 g++ 和 clang 产生警告(告诉我匿名结构在标准中不被明确允许),Visual Studio 编译代码而不产生任何警告。
我的问题是:是否有一种现代 C++1x 方法可以编写具有相同功能的相同代码,而不仅仅是命名结构?
由于 C++ 与 C 相比的限制,我看不到在标准 C++ 中执行此操作的任何有效、合法和优雅的方法。您只能选择三个属性中的两个:)
高效合法,但不够优雅
struct myBits
{
void set_bits(size_t start_bit, size_t end_bit, uint16_t value)
{
size_t len = end_bit - start_bit + 1;
uint16_t mask = ((1 << len) - 1) << (start_bit - 1);
word = (word & ~mask) | ((value << (start_bit - 1)) & mask);
}
uint16_t get_bits(size_t start_bit, size_t end_bit)
{
size_t len = end_bit - start_bit + 1;
return (word >> (start_bit - 1)) & ((1 << len) - 1);
}
uint16_t word;
};
在您的场景中使用它:
myBits mb;
mb.set_bits(1, 10, 10);
mb.set_bits(1, 8, 2);
这可能真的不如问题中的代码有效,这实际上取决于编译器如何生成用于访问位域的代码与上面的代码。与初始解决方案相比,这样做的好处是您可以访问任何位子集,而无需为其定义新的结构和位域。
合法优雅,但效率不高
template<size_t start_bit, size_t end_bit>
struct bit_field
{
bit_field(uint16_t& w) : word(w) {}
operator uint16_t() const
{
return (word >> (start_bit - 1)) & ((1 << len) - 1);
}
bit_field& operator=(uint16_t value)
{
uint16_t mask = ((1 << len) - 1) << (start_bit - 1);
word = (word & ~mask) | ((value << (start_bit - 1)) & mask);
return *this;
}
const size_t len = end_bit - start_bit + 1;
uint16_t &word;
};
struct Word
{
Word(uint16_t w) : word(w), a(word), b(word), c(word), d(word) {}
uint16_t word;
bit_field<1, 8> a;
bit_field<9, 16> b;
bit_field<1, 10> c;
bit_field<11, 16> d;
};
这种情况下的用法与您的示例一样优雅:
Word w(0);
w.c = 10;
w.a = 2;
这种方法的问题在于它确实 space 效率低下。与仅存储位的初始方法相比,您必须为每个位字段声明一个结构。
高效优雅,但不合法
这基本上就是您在问题中描述的方式。