Visual C ++相当于GCC的__attribute__((__packed__))
对于一些编译器来说,有一个结构体的包装说明符,例如::
RealView ARM编译器有“__packed” Gnu C编译器有“__attribute__((__packed__))” Visual C ++没有对等的,它只有“#pragma pack(1)”
我需要一些我可以放入结构定义的东西。
任何信息/黑客/build议? TIA …
我不知道这样做的方法,但是你可能会做这样的事情:
#include "packed.h" struct Foo { /* members go here */ } PACKED; #include "endpacked.h"
然后对于MSVC,packed.h:
#define PACKED #pragma pack(push,1)
endpacked.h
#pragma pack(pop) #undef PACKED
对于gcc,packed.h:
#define PACKED __attribute__ ((__packed__))
endpacked.h:
#undef PACKED
基本上,包装太平台依赖。 假设你的打包结构有8位的字段,并考虑一些16位字节的系统。 它不能仅仅通过打包来表示数据的结构 – 在两个系统之间传输时,您必须知道8位字节是如何转换为16位字节的。 在16位机器上的结构可能需要位域,在这种情况下,你必须知道如何执行它们。
所以,如果代码的目的是一般的可移植的,你可能只需要在你的头文件的平台特定部分定义你需要的任何打包结构。 或者说,构build你的代码,以便未来的端口可以做到这一点。
你可以像这样为GNU gcc定义PACK
#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
像这样的Visual C ++:
#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) )
像这样使用它:
PACK( struct myStruct { int a; int b; });
我知道这个问题现在已经很老了,但是我相信比之前发布的解决scheme有更好的解决scheme。 毕竟,在MSVC的情况下,可以把结构声明行中的杂注。 考虑以下几点:
#ifdef _MSC_VER # define PACKED_STRUCT(name) \ __pragma(pack(push, 1)) struct name __pragma(pack(pop)) #elif defined(__GNUC__) # define PACKED_STRUCT(name) struct __attribute__((packed)) name #endif
那么这可以像这样使用:
typedef PACKED_STRUCT() { short a; int b } my_struct_t; PACKED_SRUCT(my_other_struct) { short a; int b };
等等
这里的关键是__pragma的使用只需要在结构的声明行的周围。 这需要包含结构名称,如果它是给定的,因此名称是macros的参数。 当然,这很容易扩展到枚举/类,我将作为一个练习离开读者!
包文档MSDN页上的testing程序对validation这一点很有用。
编辑
结果在我的testing中,我在Windows上使用了Intel Compiler。 使用icl.exe这种方法没有问题,但与微软编译器(cl.exe),它不(用2010年和2013年testing)。
另一个解决scheme,取决于你需要支持哪些编译器,需要注意的是GCC至less支持4.0.4版本的Microsoft样式包装编译指示(在线文档可以从gnu.org获得版本3.4.6和4.0.4 – 前者中没有描述编译指示,后者则在后者中)。 这可以让你在结构定义之前使用#pragma pack(push,1)
在定义之后使用#pragma pack(pop)
,并且在其中进行编译。
由于GCC支持VC ++包相关的编译指示,你可以反过来做。 在这里寻找更多的信息。
提取…
为了与Microsoft Windows编译器兼容,GCC支持一组
#pragma
指令,这些指令改变了随后定义的结构成员(非零宽度位域),联合和类的最大alignment。 下面的n值总是要求是2的小幂,并以字节为单位指定新的比对。
#pragma pack(n)
只需设置新的alignment方式。
#pragma pack()
将alignment设置为编译开始时有效的alignment方式(另请参阅命令行选项-fpack-struct[=<n>]
查看代码Gen选项)。
#pragma pack(push[,n])
将内部堆栈上的当前alignment设置#pragma pack(push[,n])
然后可以select设置新alignment。
#pragma pack(pop)
将alignment设置恢复为保存在内部堆栈顶部的alignment设置(并删除该堆栈条目)。注意
#pragma pack([n])
不会影响这个内部堆栈。 因此可以有#pragma pack(push)
后跟多个#pragma pack(n)
实例,并由一个#pragma pack(pop)
。有些目标,例如i386和powerpc,支持
ms_struct
#pragma
,它将结构描述为logging的__attribute__((ms_struct))
。
#pragma ms_struct on
打开声明的结构的布局。
#pragma ms_struct off
closures声明结构的布局。
#pragma ms_struct reset
回到默认布局。
为什么你需要去结构中的东西?
我认为#pragma pack(1)
是一样的,还是我错过了什么?
你可以这样做:
struct Foo { #pragma pack(push, 1) int Bar; #pragma pack(pop) };
但它看起来很丑。