我经常发现自己必须代表一个由非常小的值组成的结构.例如,Foo有4个值a, b, c, d,范围从0 to 3.通常我不在乎,但有时,这些结构是
用于紧密循环;
他们的价值读数十亿次/秒,这是该计划的瓶颈;
整个计划由数十亿美元组成Foo;
在这种情况下,我发现自己无法决定如何Foo有效地表达.我基本上有4种选择:
struct Foo {
int a;
int b;
int c;
int d;
};
struct Foo {
char a;
char b;
char c;
char d;
};
struct Foo {
char abcd;
};
struct FourFoos {
int abcd_abcd_abcd_abcd;
};
Run Code Online (Sandbox Code Playgroud)
它们分别使用128,32,8,8位Foo,从稀疏到密集.第一个例子可能是最语言的例子,但使用它实际上会增加16倍于程序的大小,这听起来不太合适.而且,大部分内存都会被零填充而根本不被使用,这让我想知道这不是浪费.另一方面,密集地打包它们会带来额外的开销来阅读它们.
在结构中表示小值的计算"最快"方法是什么?
#include <stdio.h>
typedef struct size
{
unsigned int a:1;
unsigned int b:31;
unsigned int c:1;
} mystruct;
int main()
{
mystruct a;
printf("%d", sizeof(a));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
int b:31,输出为8.int b:1,输出为4.int b:32,输出为12.有人能解释一下这个原因吗?
如何在Swift中声明和使用位字段?
声明这样的枚举确实有效,但尝试将OR 2值一起编译失败:
enum MyEnum: Int
{
case One = 0x01
case Two = 0x02
case Four = 0x04
case Eight = 0x08
}
// This works as expected
let m1: MyEnum = .One
// Compiler error: "Could not find an overload for '|' that accepts the supplied arguments"
let combined: MyEnum = MyEnum.One | MyEnum.Four
Run Code Online (Sandbox Code Playgroud)
我查看了Swift如何导入Foundation枚举类型,它通过定义struct符合RawOptionSet协议的方式来实现:
struct NSCalendarUnit : RawOptionSet {
init(_ value: UInt)
var value: UInt
static var CalendarUnitEra: NSCalendarUnit { get }
static …Run Code Online (Sandbox Code Playgroud) 我刚刚用bitfields做了一个测试,结果令我感到惊讶.
class test1 {
public:
bool test_a:1;
bool test_b:1;
bool test_c:1;
bool test_d:1;
bool test_e:1;
bool test_f:1;
bool test_g:1;
bool test_h:1;
};
class test2 {
public:
int test_a:1;
int test_b:1;
int test_c:1;
int test_d:1;
int test_e:1;
int test_f:1;
int test_g:1;
int test_h:1;
};
class test3 {
public:
int test_a:1;
bool test_b:1;
int test_c:1;
bool test_d:1;
int test_e:1;
bool test_f:1;
int test_g:1;
bool test_h:1;
};
Run Code Online (Sandbox Code Playgroud)
结果如下: -
sizeof(test1) = 1 // This is what I'd expect. 8 bits in a byte …Run Code Online (Sandbox Code Playgroud) 您可以使用枚举类实现标准符合(如n3242草案的17.5.2.1.3所述)类型安全位掩码吗?我读它的方式,类型T是一个位掩码,如果它支持|,&,^,〜,| =,&=和^ =运算符,你还可以做if(l&r)其中l和r是T类型.列表中缺少的是运算符!=和==并允许排序一个也可能想要重载<.
让操作员工作只是烦人的样板代码,但我不知道如何(l&r).至少下面的代码不能用GCC编译(除了极其危险,因为它允许错误的隐式转换为int):
enum class Foo{
operator bool(){
return (unsigned)*this;
}
};
Run Code Online (Sandbox Code Playgroud)
编辑:我现在肯定知道枚举类不能有成员.实际问题如果(l&r)仍然存在.
在我的第一个例子中,我使用了两个位域int64_t.当我编译并获得类的大小时,我得到8.
class Test
{
int64_t first : 40;
int64_t second : 24;
};
int main()
{
std::cout << sizeof(Test); // 8
}
Run Code Online (Sandbox Code Playgroud)
但是,当我将第二个bitfeild更改int32_t为类的大小时,会增加到16:
class Test
{
int64_t first : 40;
int32_t second : 24;
};
int main()
{
std::cout << sizeof(Test); // 16
}
Run Code Online (Sandbox Code Playgroud)
这种情况发生在GCC 5.3.0和MSVC 2015上.但为什么呢?
我有四面旗帜
Current = 0x1
Past = 0x2
Future = 0x4
All = 0x7
Run Code Online (Sandbox Code Playgroud)
假设我收到了两个标志Past和Future(setFlags(PAST | FUTURE)).我怎么知道它Past是否在里面?同样,我怎么能告诉它Current不在其中?这样我就不必测试每种可能的组合.
我不完全确定C,但C++允许未命名的0字段位字段.例如:
struct X
{
int : 0;
};
Run Code Online (Sandbox Code Playgroud)
在冰犯罪的回答之后编辑了这个例子
编辑:好的,多亏了目前的答案,我现在知道了理论目的.但问题是关于实际用途,所以他们仍然持有:)
说,我有以下结构:
typedef struct my_struct{
unsigned long a;
unsigned long b;
char* c;
unsigned int d1 :1;
unsigned int d2 :4;
unsigned int d3 :4;
unsigned int d4 :23;
} my_type, *p_type;
Run Code Online (Sandbox Code Playgroud)
该字段d3目前由直到#define达到的s 定义.0x000x0D
实际上,d3是一个枚举.所以很有可能继续前进并取而代之
unsigned int d3 :4;
Run Code Online (Sandbox Code Playgroud)
通过
my_enum d3 :4;
Run Code Online (Sandbox Code Playgroud)
这是安全/允许的吗?
代码必须用各种编译
显然,我可以保留d3原样的定义并在我的代码中使用枚举,将其分配给d3等等,但这不适用于C++.
我想在Delphi中声明一个包含与C中相同布局的记录.
对于那些感兴趣的人:此记录是Windows操作系统的LDT_ENTRY记录中的联合的一部分.(我需要在Delphi中使用此记录,因为我正在使用Delphi中的Xbox模拟器 - 请参阅sourceforge上的项目Dxbx).
无论如何,有问题的记录定义为:
struct
{
DWORD BaseMid : 8;
DWORD Type : 5;
DWORD Dpl : 2;
DWORD Pres : 1;
DWORD LimitHi : 4;
DWORD Sys : 1;
DWORD Reserved_0 : 1;
DWORD Default_Big : 1;
DWORD Granularity : 1;
DWORD BaseHi : 8;
}
Bits;
Run Code Online (Sandbox Code Playgroud)
据我所知,Delphi中没有可用的位域.我试过这个:
Bits = record
BaseMid: Byte; // 8 bits
_Type: 0..31; // 5 bits
Dpl: 0..3; // 2 bits
Pres: Boolean; // 1 bit
LimitHi: 0..15; // 4 bits
Sys: Boolean; …Run Code Online (Sandbox Code Playgroud)