这个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个字节,等等。)
答案 0 :(得分:2)
这似乎在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)
答案 1 :(得分:1)
这是一个可以在 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;
}
答案 2 :(得分: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 directive。获取a,b,c值的方法是引用并集中每个相应结构中的V字段。例如,如果你的类型是u_t,那么
u.c.V = 17;
答案 3 :(得分:0)
您可以使用union,也许使用一些#defines来简化使用。
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
};
答案 4 :(得分:0)
不完全符合您的要求,但您应该可以使用bit fields获得类似的效果。
此外,对于Visual C ++,可能值得一看:__declspec(align(#))
或#pragma pack
。
答案 5 :(得分:0)
使用union的替代方法是使用方法来访问值,正如您可能应该做的那样。虽然它是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