C 宏的容器';s基准参考变更
让我们假设一个结构,当它的成员c的地址已知时,我们想要确定容器地址C 宏的容器';s基准参考变更,c,kernel,linux-device-driver,C,Kernel,Linux Device Driver,让我们假设一个结构,当它的成员c的地址已知时,我们想要确定容器地址 struct some_data { char a; int b; char c; int d; }; 在container_of()宏中,在偏移量计算过程中,将基址更改为一个新的引用(0),然后针对该新的基址引用,按如下方式测量成员(例如c)的of集: long offset=(long)(&(struct some_data*)0)->c-0 这很好用。现在,根据更改基本引用的概念,以下内容也应该起作用:(我希望) lo
struct some_data {
char a;
int b;
char c;
int d;
};
在container_of()宏中,在偏移量计算过程中,将基址更改为一个新的引用(0),然后针对该新的基址引用,按如下方式测量成员(例如c)的of集:
long offset=(long)(&(struct some_data*)0)->c-0代码>
这很好用。现在,根据更改基本引用的概念,以下内容也应该起作用:(我希望)
long offset=(long)(&(struct some_data*)100)->c-100代码>
但事实证明,这是行不通的。您能帮我理解这里的错误吗。我认为这段代码定义得不好。你应该使用标准的Coffset of
,而不是像这样的黑客。我尝试了问题中显示的代码,两个表达式都将offset
设置为8,这在32位int
与4字节边界对齐的系统上是有意义的。当然,如果将->c
更改为->b
或->d
,它将不起作用。你说的“不起作用”是什么意思?虽然是UB,但GCC在这两种情况下都产生8
的结果。参见https://godbolt.org/z/sf8YhvGoM
。在我看来,展示UB是如何影响你的代码是有益的。@monzurulislam,你的例子是不相关的。some_data::z
的类型是int
。指针运算会出错。使用some_data::y
在这两种情况下都会产生正确的结果。我认为您真正想要做的(处理大小大于1的成员)应该是long offset=(long)和((struct some_data*)100)->c-100代码>。