焊盘a C++;结构为二的幂 我正在为嵌入式系统开发一些C++代码。代码使用的I/O接口要求每条消息的大小(以字节为单位)为2的幂。现在,代码执行类似的操作(在几个地方):
我第一次尝试在64位Fedora上编译代码,其中焊盘a C++;结构为二的幂 我正在为嵌入式系统开发一些C++代码。代码使用的I/O接口要求每条消息的大小(以字节为单位)为2的幂。现在,代码执行类似的操作(在几个地方):,c++,struct,bit-manipulation,padding,C++,Struct,Bit Manipulation,Padding,我第一次尝试在64位Fedora上编译代码,其中long是64位。在这种情况下,sizeof(internal)大于64,数组大小表达式下溢,编译器抱怨数组太大 理想情况下,我希望能够编写一个宏,该宏将获取结构的大小,并在编译时计算填充数组所需的大小,以便将结构的大小四舍五入到二的幂 我已经看过了这个页面,但我不知道那里的任何技术是否真的可以在编译时评估的宏中实现 这个问题还有其他解决办法吗?或者我应该把这个问题永久化,把神奇的64变为神奇的128?为什么不使用一个联盟 union Messag
long
是64位。在这种情况下,sizeof(internal)
大于64,数组大小表达式下溢,编译器抱怨数组太大
理想情况下,我希望能够编写一个宏,该宏将获取结构的大小,并在编译时计算填充数组所需的大小,以便将结构的大小四舍五入到二的幂
我已经看过了这个页面,但我不知道那里的任何技术是否真的可以在编译时评估的宏中实现
这个问题还有其他解决办法吗?或者我应该把这个问题永久化,把神奇的64变为神奇的128?为什么不使用一个联盟
union Message
{
struct internal_
{
unsigned long member1;
/* more members */
};
char[64];
};
或者最好使用匿名结构
union Message
{
struct
{
unsigned long member1;
/* more members */
};
char[64];
};
因此,您可以像这样访问成员:Message.member1
编辑:显然,这并不能解决大于64的问题,但提供了一种更干净的填充方式。最明显的方式可能是只使用三元运算符:
#define LOG2_CONST(n) ((n) <= 1 ? 0 :
((n) <= 2 ? 1 :
((n) <= 4 ? 2 :
/* ... */
))))))))))))))))))))))))))))))
#define PADDED_STRUCT(ResultName, BaseName) \
typedef union { BaseName data; char pad[1 << LOG2_CONST(sizeof(BaseName))]; } ResultName
#define LOG2_CONST(n)((n)解决此问题的一种方法是用大小的倍数(long)替换硬编码的64,将填充变成如下内容:
char pad[4*sizeof(unsigned long) - sizeof(internal_)];
它很难看,但应该可以移植到64位
这就是说,要求消息大小为2的幂的API听起来有点奇怪,就像设计问题一样。要求消息大小为偶数是有道理的,因为在某些处理器上,访问奇数地址上的数据要付出相当大的代价,但你的#pragma包几乎不可避免地会造成这种情况。写一个小包装怎么样send and receive message函数可以处理任意大小的消息,它们只需分配一个更大的缓冲区(下一次幂为2)并清除它,将结构复制到开头并发送。union message
union Message
{
struct
{
unsigned long member1;
unsigned long member2; //...
};
char pad[1 << 5]; //change 5 to whatever size you need...
};
{
结构
{
未签名的长成员1;
未签名的长成员2;//。。。
};
char pad[1使用模板元程序(根据注释进行编辑)
#包括
#包括
使用名称空间std;
模板
结构P
{
枚举{val=P::val*2};
};
模板
结构P
{
枚举{val=1};
};
模板
结构焊盘尺寸
{
枚举{val=P::val-sizeof(T)};
};
模板
结构可能已添加
{
T有效载荷;
炭垫[N];
};
模板
结构可能已添加
{
T有效载荷;
};
模板
结构持有者:已添加公共可能
{
};
int main()
{
typedef char Arr[6];
持有人;
cout我喜欢,尤其是匿名结构的部分
答案没有解决的一件事是大于64字节的问题,但是可以通过有条件地声明char[128]struct成员(如果sizeof(long)==8并声明char[64]来解决否则。您可以使用模板获得结构大小的编译时常量,四舍五入为二次方:
template<int N, int C = 1>
struct Recurse
{
enum {result = Recurse<N/2, C*2>::result};
};
template<int C>
struct Recurse<0, C>
{
enum {result = C};
};
template<typename T>
struct Calc
{
enum {size = Recurse<sizeof(Test)-1>::result};
};
struct Test
{
int a;
double b;
double c;
};
int main()
{
std::cout << sizeof(Test) << " -> " << Calc<Test>::size << std::endl;
return 0;
}
模板
结构递归
{
枚举{result=Recurse::result};
};
模板
结构递归
{
枚举{result=C};
};
模板
结构计算
{
枚举{size=Recurse::result};
};
结构测试
{
INTA;
双b;
双c;
};
int main()
{
std::cout和另一个模板解决方案(从中大量掠夺):
#包括
#包括
使用名称空间std;
模板
结构焊盘尺寸
{
静态常数int val=
(焊盘尺寸
struct PadSize//一旦TSize设置为您就已经在使用#pragma pack
,我不知道是什么编译器您可以专门使用,但您应该看看它们是否支持控制对齐/填充的pack参数,然后您就可以完全去掉填充字段。我知道pragma pack的版本也支持这一点。您可以按如下方式进行宏化(对于32位体系结构):
然后,您可以使用联合技巧或其他方法应用该方法。在您的示例中:
#pragma pack(1)
struct Message
{
struct internal_
{
unsigned long member1;
unsigned long member2;
unsigned long member3;
/* more members */
} internal;
char pad[alignment_padding(sizeof(internal_))];
};
#pragma pack()
我喜欢这样,但是当内容是2的偶数幂时,它失败了。pad的声明得到错误C2466:无法分配一个常量大小的数组0我想您可以从T派生出PossiblyPadded,而不是拥有一个T成员(对于合适的T),并省去烦人的成员访问语法。@fizzer,这能保证不添加填充吗?我自己会使用一个联合。而且你总是可以使用T*运算符->()…谢谢!我也喜欢bdonlan的答案,但我认为这可能是一个更好的通用解决方案。我喜欢它!我是在寻找一种在编译时获得下一个二次幂的模板元编程方法时发现的。效果很好!我喜欢它,我没有想到使用宏来处理重复的n | n>>1,2,4,8…等等。实际上这是危险的s、 由于member1和member2不会在不同平台上的同一地址对齐。由于这是IO代码,这将导致错误。
template<int N, int C = 1>
struct Recurse
{
enum {result = Recurse<N/2, C*2>::result};
};
template<int C>
struct Recurse<0, C>
{
enum {result = C};
};
template<typename T>
struct Calc
{
enum {size = Recurse<sizeof(Test)-1>::result};
};
struct Test
{
int a;
double b;
double c;
};
int main()
{
std::cout << sizeof(Test) << " -> " << Calc<Test>::size << std::endl;
return 0;
}
#include <iostream>
#include <ostream>
using namespace std;
template <int TSize, int PSize = 1, bool = false>
struct PadSize
{
static const int val =
( PadSize < TSize, (PSize*2), (TSize <= (PSize*2) ) > :: val );
};
template < int TSize, int PSize>
struct PadSize <TSize, PSize, true> // As soon as TSize is <= to PSize
{
static const int val = PSize;
};
int main()
{
typedef char Arr[8];
char pad[ PadSize <sizeof(Arr)>::val ];
cout << sizeof pad << endl;
}
#define align_step(N, shift) ((N) | ((N) >> shift))
#define align_up(N) (align_step(align_step(align_step(align_step(align_step((N)-1, 1), 2), 4), 8), 16) + 1)
#define alignment_padding(N) (align_up((N)) - (N))
#pragma pack(1)
struct Message
{
struct internal_
{
unsigned long member1;
unsigned long member2;
unsigned long member3;
/* more members */
} internal;
char pad[alignment_padding(sizeof(internal_))];
};
#pragma pack()