我使用的是开源库(Easy C State Machine)。当我查看代码时,我发现结构是通过基地址+偏移X来访问的,如下所示。
#define OFF_SET_OF_XX 1
#define GET_MEMBER(X, Y, Z) ((X)(*((X*)(((int*)(Y))+Z))))
typedef struct Foo {
int i;
int XX;
}Foo;
Foo *foo1 = alloc(...);
int j = GET_MEMBER(int, foo1, OFF_SET_OF_XX);
而不是:
Foo *foo1 = alloc(...);
int j = foo1->XX;
以上两者有什么区别?前者的任何优势?
该库是用ANSI C编写的。但据说它只能支持两种架构: x86和amd64。由于我想在另一个arch上使用它,我查看了源代码,发现唯一与架构相关的代码是OFF_SET_OF_XXs。
答案 0 :(得分:2)
首先,我想指出最左侧的演员类型X
不是必需的,所以你可以将其简化为:
#define GET_MEMBER(X, Y, Z) (*((X*)(((int*)(Y))+Z)))
但是,我没有看到像这样使用宏的目的。它抛弃了类型安全性,语法很麻烦。
编译器为两种不同方式生成的代码应该非常相似,如果不相同的话。但是这个库应该编译的编译器和平台是什么?如果在该编译器中使用GET_MEMBER
恰好获得了性能提升,那么这就是他们使用它的原因。
编辑1:我的猜测是该库的原作者不了解结构并发明了类似于使用alloc,pointers和mac的结构的自己的东西。现在他已经将库变为开源,其他人正在尝试将其转换为使用结构,但是有很多代码需要转换,而且还没有完成。
答案 1 :(得分:1)
我看到的最合适的用途(边界线,IMO)是Linux内核的container_of宏。
但是对于你给出的例子,除了“作者是白痴”之外,绝对没有理由这样做。它在性能上没有任何好处,牺牲了可读性,并且引发了烦人的错误(例如,如果有人决定有一天将i
更改为long
会发生什么?)