具有显式(手动)字段布局的C结构体/联合
本文关键字:布局 结构体 联合 字段 手动 | 更新日期: 2023-09-27 18:06:30
这段c#代码的C等效是什么?
[StructLayout(LayoutKind.Explicit)]
struct Test
{
[FieldOffset(0)] int a; // Integer at byte offset 0
[FieldOffset(1)] int b; // Integer at byte offset 1
[FieldOffset(3)] int c; // Integer at byte offset 3
};
(我不在乎它是否不可移植,例如int
被认为是4字节,等等)
这似乎在Visual Studio下工作得很好:
#pragma pack(push)
#pragma pack(1)
typedef union
{
int a;
struct
{
char unused0;
int b;
};
struct
{
char unused1;
char unused2;
char unused3;
int c;
};
} Test;
#pragma pack(pop)
这是一个宏,应该工作在clang, gcc和msvc(尚未测试msvc版本):
#define YDUMMY(suffix, size) char dummy##suffix[size]
#define XDUMMY(suffix, size) YDUMMY(suffix, size)
#define DUMMY(size) XDUMMY(__COUNTER__, size)
#ifdef __GNUC__
#define EXPLICIT_UNION_START(name) union Test {
#define EXPLICIT_UNION_END() };
#define EXPLICIT_OFFSET_FIELD(foff, ftype, fname) struct __attribute__((packed)) { DUMMY(foff); ftype fname; };
#elif defined(_MSC_VER)
#define EXPLICIT_UNION_START(name) #pragma pack(push, 1) '
union Test {
#define EXPLICIT_UNION_END() }; '
#pragma pack(pop)
#define EXPLICIT_OFFSET_FIELD(foff, ftype, fname) struct { DUMMY(foff); ftype fname; };
#else
#error "What compiler is this?"
#endif
EXPLICIT_UNION_START(Test)
EXPLICIT_OFFSET_FIELD(0, int, a)
EXPLICIT_OFFSET_FIELD(1, int, b)
EXPLICIT_OFFSET_FIELD(3, int, c)
EXPLICIT_UNION_END()
由于未命名字段,访问已定义字段的语法不会受到虚拟名称的污染:
int main() {
union Test t;
t.b = 13;
printf("offset a = %zx'n", offsetof(union Test, a));
printf("offset b = %zx'n", offsetof(union Test, b));
printf("offset c = %zx'n", offsetof(union Test, c));
printf("t.b = %d'n", t.b);
return 0;
}
这个怎么样
union u_t {
struct {
int V;
} a;
struct {
byte dummy;
int V;
} b;
struct {
byte dummy1;
byte dummy2;
byte dummy3;
int V;
} c;
};
虚拟字段用于强制偏移。我认为一些编译器可以强制字段或结构对齐,所以你需要确保在编译时,那个选项是关闭的。参见pragma pack指令。获取a, b, c值的方法是在联合中的每个结构体中引用V字段。例如,如果u是u_t类型,则
u.c.V = 17;
您可以使用联合,或者使用一些#定义来简化使用。
union Test {
struct {
int V_a;
} s_a;
struct {
char V_a;
int V_b;
} S_b;
struct {
char V_a;
short V_b;
int V_c;
} S_c;
#define a S_a.V_a
#define b S_b.V_b
#define c S_c.V_c
};
不完全符合您的要求,但您应该能够使用位字段实现类似的效果。
同样,对于Visual c++, __declspec(align(#))
或#pragma pack
可能值得一看。
使用联合的另一种选择是使用方法来访问这些值,因为您可能无论如何都应该这样做。虽然它是c++,你要求的C -但我假设c++是好的基于你使用vc++。
#ifdef __cplusplus
struct Test {
int a() {
return *(int*)&values_[0];
}
void a(int value) {
*(int*)&values_[1] = value;
}
int b() {
return *(int*)&values_[1];
}
void b(int value) {
*(int*)&values_[1] = value;
}
int c() {
return *(int*)&values_[3];
}
void c(int value) {
*(int*)&values_[3] = value;
}
private:
char[8] values_;
};
#endif