在C结构中,可以指定另一个位长度,而不是类型的默认位长度,如下所示:
struct MyStruct{
int myVar : 1; //Size of myVar is 1 bit (so it can take values 0 or 1
int myOtherVar: 4; //Size of myOtherVar is 4 bits (so it can take values 0 to 15)
}
Run Code Online (Sandbox Code Playgroud)
这称为位字段.
我的问题是,是否也可以在C++类中执行此操作,如下所示:
class MyClass{
public:
//Some methods
private:
int m_myAttribute : 1;
int m_myOtherAttribute : 4;
}
Run Code Online (Sandbox Code Playgroud)
我在网上搜索了这个,但我找到的所有比特字段的例子都使用了结构,而不是类.
我测试了这段代码并且编译得很好,但是我想知道属性的大小是否真的是指定的大小,或者编译器是否忽略了位字段并使用了标准int大小.
bitfield是C概念还是C++?
它只能在结构中使用吗?我们可以使用它们的其他地方是什么?
AFAIK,bitfields是特殊的结构变量,只占用指定的no.比特.它有助于节省内存而不是其他任何东西.我对么?
我编写了一个小程序来理解位域的使用 - 但是,我认为它没有按预期工作.我希望下面结构的大小为1 + 4 + 2 = 7个字节(考虑到unsigned int的大小在我的机器上是4个字节),但令我惊讶的是,结果是12个字节(4 + 4 + 4) ).谁能让我知道为什么?
#include <stdio.h>
struct s{
unsigned int a:1;
unsigned int b;
unsigned int c:2;
};
int main()
{
printf("sizeof struct s = %d bytes \n",sizeof(struct s));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
OUTPUT:
sizeof struct s = 12 bytes
Run Code Online (Sandbox Code Playgroud) C语言的位域提供了一种在结构中定义任意宽度字段的相当方便的方法(永远不要在一分钟内解决可移植性问题.)例如,这是一个带有几个字段和'flag'的简单结构:
#pragma pack(push,1)
struct my_chunk{
unsigned short fieldA: 16;
unsigned short fieldB: 15;
unsigned short fieldC: 1;
};
#pragma pop()
Run Code Online (Sandbox Code Playgroud)
添加#pragma语句将此结构打包成一个32位字(确保指针的指针操作my_chunk对齐,例如,节省空间).
访问每个字段在语法上非常好:
struct my_chunk aChunk;
aChunk.fieldA = 3;
aChunk.fieldB = 2;
aChunk.fieldC = 1;
Run Code Online (Sandbox Code Playgroud)
在没有语言帮助的情况下执行此操作的替代方法相当丑陋,并且几乎可以转换为汇编程序.例如,一种解决方案是为要访问的每个字段设置bitshift宏:
#define FIELD_A 0xFF00
#define FIELD_B 0x00FE
#define FIELD_C 0x0001
#define get_field(p, f) ((*p)&f)
#define set_field(p, f, v) (*p) = (v<<f) + (*p)&(~f)
...
set_field(&my_chunk, FIELD_A, 12345);
Run Code Online (Sandbox Code Playgroud)
..或类似的东西(为了更正式,看看这个)
所以问题是,如果我想在go中"做"bitfields,这样做的最佳做法是什么?
我有一个对象集合,每个对象都有一个位字段枚举属性.我想要得到的是整个集合中位字段属性的逻辑OR.如何通过循环遍历集合(希望使用LINQ和lambda)来完成此操作?
这是我的意思的一个例子:
[Flags]
enum Attributes{ empty = 0, attrA = 1, attrB = 2, attrC = 4, attrD = 8}
class Foo {
Attributes MyAttributes { get; set; }
}
class Baz {
List<Foo> MyFoos { get; set; }
Attributes getAttributesOfMyFoos() {
return // What goes here?
}
}
Run Code Online (Sandbox Code Playgroud)
我试过这样用.Aggregate:
return MyFoos.Aggregate<Foo>((runningAttributes, nextAttributes) =>
runningAttributes | nextAttribute);
Run Code Online (Sandbox Code Playgroud)
但这不起作用,我无法弄清楚如何使用它来得到我想要的东西.有没有办法使用LINQ和一个简单的lambda表达式来计算这个,或者我只是在集合上使用循环?
注意:是的,这个示例案例很简单,基本foreach将是要走的路,因为它简单且不复杂,但这只是我实际使用的简化版本.
我有一个带有位字段的结构(总共32位宽度),我有一个32位变量.当我尝试将变量值分配给我的结构时,我收到一个错误:
错误:从'uint32_t {aka unsigned int}'转换为请求的非标量类型'main():: CPUID'.
struct CPUIDregs
{
uint32_t EAXBuf;
};
CPUIDregs CPUIDregsoutput;
int main () {
struct CPUID
{
uint32_t Stepping : 4;
uint32_t Model : 4;
uint32_t FamilyID : 4;
uint32_t Type : 2;
uint32_t Reserved1 : 2;
uint32_t ExtendedModel : 4;
uint32_t ExtendedFamilyID : 8;
uint32_t Reserved2 : 4;
};
CPUID CPUIDoutput = CPUIDregsoutput.EAXBuf;
Run Code Online (Sandbox Code Playgroud)
你知道如何以最短的方式做到这一点吗?谢谢
PS当然我在实际代码中有更合适的EAX值,但我想这不会影响到这里.
我在C中有一个8位的标志,我想使用这样的位字段逐位访问它:
#include <stdio.h>
#include <stdint.h>
int main(void) {
struct flags{
uint8_t bits1:1;
uint8_t bits2:1;
uint8_t bits3:1;
uint8_t bits4:1;
uint8_t bits5:1;
uint8_t bits6:1;
uint8_t bits7:1;
uint8_t bits8:1;
};
struct flags *my_flags;
uint8_t x=6,i;
my_flags=(struct flags *)&x;
printf("%u\t",my_flags->bits5);
printf("%u\t",my_flags->bits6);
printf("%u\t",my_flags->bits7);
printf("%u\t",my_flags->bits8);
printf("%u\t",my_flags->bits1);
printf("%u\t",my_flags->bits2);
printf("%u\t",my_flags->bits3);
printf("%u\t",my_flags->bits4);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我得到了预期的输出:0 0 0 0 0 1 1 0.
但这有点太多编码.
my_flags->bits_i中有什么类似的东西,i它将成为循环中的计数器吗?我知道默认情况下两者都不存在.但有没有其他方法可以实现相同的目标?
参见在线示例: Ideone示例
struct {
union {
struct {
uint32_t messageID : 26;
uint8_t priority : 3;
} __attribute__ ((packed));
uint32_t rawID : 29;
} __attribute__ ((packed));
uint8_t canFlags : 3;
} __attribute__ ((packed)) idSpecial;
Run Code Online (Sandbox Code Playgroud)
为什么编译器会将结构的大小报告为5个字节而不是4个?它应该包含32位.
我即将实施Eratosthenes筛,并对筛阵有一个普遍的问题.
我现在已经实施了几次筛子(在C中),并且总是使用一组uint8_t(外<stdint.h>)作为筛子.这是非常低效的内存,因为每个数字都使用8位来筛选,即使一位应该足够.
我怎么会用C来解决这个问题呢?我需要一个位数组.我可以几乎创建任何类型的(阵列uint8_t,uint16_t,uint32_t,uint64_t),并与比特掩码等访问单个位
我应该选择哪种数据类型以及在没有性能损失的情况下应该使用哪些操作来访问这些位?
PS:我不认为这是一个重复的只是一个BitArray实现,因为它的问题是具体的关于埃拉托色尼的筛,因为它的主要性质必须是有效的(不仅在内存使用情况,但在访问).我在想,也许可以使用不同的技巧来使筛分过程更有效...
假设我有以下定义:
#include <stdbool.h>
#include <stdint.h>
#define ASSERT(cond) _Static_assert(cond, #cond)
typedef union {
struct {
bool bit0:1;
bool bit1:1;
bool bit2:1;
bool bit3:1;
bool bit4:1;
bool bit5:1;
bool bit6:1;
bool bit7:1;
};
uint8_t bits;
} byte;
ASSERT(sizeof(byte) == sizeof(uint8_t));
Run Code Online (Sandbox Code Playgroud)
能不能写个代码,比如
#include <assert.h>
// ...
assert(((byte) { .bit0 = 1 }).bits == 0b00000001);
assert(((byte) { .bit1 = 1 }).bits == 0b00000010);
assert(((byte) { .bit2 = 1 }).bits == 0b00000100);
assert(((byte) { .bit3 = 1 }).bits == 0b00001000);
assert(((byte) { .bit4 = 1 …Run Code Online (Sandbox Code Playgroud) 只是出于好奇,如果我有一个带有位字段的结构
struct Foo
{
char a : 1;
char b : 1;
char c : 1;
}
Run Code Online (Sandbox Code Playgroud)
另一个带有位域和 struct Foo 的结构
struct Bar
{
Foo foo;
char a : 1;
char b : 1;
char c : 1;
}
Run Code Online (Sandbox Code Playgroud)
所有这些位都会被打包成一个整数吗?
在这种情况下,这些字段是否会被重新排序以形成单个位字段?
struct Baz
{
char a : 1;
int NotBitfield;
char b : 1;
char c : 1;
}
Run Code Online (Sandbox Code Playgroud)