在C++中,我有一个包含匿名位域结构的类.我想将其初始化为零,而无需手动写出所有字段.
我可以想象将初始化放在三个地方:
这个位域有很多字段,我宁愿不列出所有字段.
例如,请参阅以下代码:
class Big {
public:
Big();
// Bitfield struct
struct bflag_struct {
unsigned int field1 : 1;
unsigned int field2 : 2;
unsigned int field3 : 1;
// ...
unsigned int field20 : 1;
// bflag_struct(); <--- Here?
} bflag;
unsigned int integer_member;
Big *pointer_member;
}
Big::Big()
: bflag(), // <--- Can I zero bflag here?
integer_member(0),
pointer_member(NULL)
{
// Or here?
}
Run Code Online (Sandbox Code Playgroud)
其中一个更好吗?或者还有其他我想念的东西?
编辑:根据下面接受的答案(Ferruccio),我决定采用这个解决方案:
class Big {
// ...
struct bflag_struct {
unsigned …Run Code Online (Sandbox Code Playgroud) 我很想知道为什么具有相同数据类型的位字段比使用混合数据类型更小.
struct xyz
{
int x : 1;
int y : 1;
int z : 1;
};
struct abc
{
char x : 1;
int y : 1;
bool z : 1;
};
Run Code Online (Sandbox Code Playgroud)
sizeof(xyz)= 4 sizeof(abc)= 12.
我正在使用VS 2005,64位x86机器.
一台机器/编译器级别的答案会很棒.
在C中是否有可移植的方法来在编译时找出位字段的掩码?
理想情况下,我希望能够原子地清除这样的字段:
struct Reference {
unsigned age : 3;
unsigned marked : 1;
unsigned references : 4;
};
struct Reference myRef;
__sync_and_and_fetch(&myRef, age, ~AGE_MASK);
Run Code Online (Sandbox Code Playgroud)
否则我必须取消对结构的锁定,这比我想要的更重.
我知道位字段是依赖于编译器的,但是我没有在最新的g ++和Visual C++ 2010上找到关于位字段的线程安全性的文档.
位字段成员的操作是原子的吗?
我正在寻找最优雅的接口上的输入来放置内存映射的寄存器接口,其中目标对象在寄存器中被分割:
union __attribute__ ((__packed__)) epsr_t {
uint32_t storage;
struct {
unsigned reserved0 : 10;
unsigned ICI_IT_2to7 : 6; // TOP HALF
unsigned reserved1 : 8;
unsigned T : 1;
unsigned ICI_IT_0to1 : 2; // BOTTOM HALF
unsigned reserved2 : 5;
} bits;
};
Run Code Online (Sandbox Code Playgroud)
在这种情况下,访问单个位T或任何reserved字段工作正常,但要读取或写入ICI_IT需求代码更像:
union epsr_t epsr;
// Reading:
uint8_t ici_it = (epsr.bits.ICI_IT_2to7 << 2) | epsr.bits.ICI_IT_0to1;
// Writing:
epsr.bits.ICI_IT_2to7 = ici_it >> 2;
epsr.bits.ICI_IT_0to1 = ici_it & 0x3;
Run Code Online (Sandbox Code Playgroud)
在这一点上,我已经失去了bitfield抽象试图提供的简单/便利的一大块.我考虑过宏观解决方案:
#define GET_ICI_IT(_e) ((_e.bits.ICI_IT_2to7 << …Run Code Online (Sandbox Code Playgroud) enum class confirm {yes};
struct item
{
confirm s:4; // (1) limiting storage size required
};
int main()
{
item itm;
itm.s = confirm::yes; // (2) OK
switch (itm.s)
{
case confirm::yes: // (3) Failure, need static data cast here?
break;
}
}
Run Code Online (Sandbox Code Playgroud)
产生错误:
In function ‘int main()’:
error: could not convert ‘yes’ from ‘confirm’ to ‘int’
case confirm::yes:
^
Run Code Online (Sandbox Code Playgroud)
用g ++编译但用clang ++编译好.为什么分配标记为(2)可能但是由(3)标记的案例条款不是?
警告约too small storage是offtopic
任何人都可以判断是否可以将一种类型的位域分配给其他类型?有了C90编译器的支持.
这是位域的结构:
typedef struct{
unsigned int ERA:2;
unsigned int destar:2;
unsigned int srcar:2;
unsigned int opcode:4;
unsigned int grp:2;
unsigned int dumy:3;
} Command;
typedef struct{
unsigned int cell:15;
} Word;
Run Code Online (Sandbox Code Playgroud)
这是主要计划:
int main(int argc, const char * argv[]){
Word word;
Command cmd;
cmd.grp = 2;
word = cmd;
}
Run Code Online (Sandbox Code Playgroud)
假设我在这里有这15位:
我们按此顺序排列:
命令:
Dumy | grp | opcode | srcar | destar | ERA
0 0 0 0 1 0 0 0 1 10 0 0 0 0
Run Code Online (Sandbox Code Playgroud)
字:
| …Run Code Online (Sandbox Code Playgroud) 位域的字节序由实现定义。有没有一种方法可以在编译时通过某个宏或其他编译器标志检查gcc的位域字节序实际上是什么?
换句话说,给定类似:
struct X {
uint32_t a : 8;
uint32_t b : 24;
};
Run Code Online (Sandbox Code Playgroud)
我有什么办法可以在编译时知道a第一个字节还是最后一个字节X吗?
我使用的是Microchip微控制器,它定义了以下结合:
__extension__ typedef struct tagT1CONBITS {
union {
struct {
uint16_t :1;
uint16_t TCS:1;
uint16_t TSYNC:1;
uint16_t :1;
uint16_t TCKPS:2;
uint16_t TGATE:1;
uint16_t :6;
uint16_t TSIDL:1;
uint16_t :1;
uint16_t TON:1;
};
struct {
uint16_t :4;
uint16_t TCKPS0:1;
uint16_t TCKPS1:1;
};
};
} T1CONBITS;
extern volatile T1CONBITS T1CONbits __attribute__((__sfr__));
Run Code Online (Sandbox Code Playgroud)
在我的代码中的某处我将变量定义为8位无符号整数,我想将其分配给上面联合的一个字段.有点如下:
uint8_t tckps;
// The value of tckps is calculated here by some magic formula
tckps = magicformula();
// We asign the value of tckps to the uC register
T1CONbits.TCKPS = tckps; …Run Code Online (Sandbox Code Playgroud) 下面的typedef是来自Atmel SAMD21 ARM MCU包含文件的DIR寄存器.由于位struct成员和reg成员都是32位,因此联合中的两个成员之间是否有任何区别?
我试图理解为什么他们不只是使用uint32_t作为DIRSET寄存器的类型.我唯一认为他们只是这样定义它与其他寄存器一致,其中bit结构中有多个字段.
typedef union {
struct {
uint32_t DIRSET:32;
} bit;
uint32_t reg;
} PORT_DIRSET_Type;
Run Code Online (Sandbox Code Playgroud) bit-fields ×10
c ×8
c++ ×5
embedded ×3
struct ×3
gcc ×2
unions ×2
arm ×1
atomic ×1
c89 ×1
constructor ×1
endianness ×1
enum-class ×1
g++ ×1
microchip ×1