C指针算术,没有结构对象
我认为这是不可能在C,但要求validation这一点。 是否有可能在没有这种types的实际variables的结构成员之间进行算术运算? 例如:
typedef struct _s1 { int a; int b; int c; } T1;
我想看看“C”成员与结构开始的偏移量。 如果我有变数,这很容易:
T1 str; int dist = (int)&str.c - (int)&str;
但是我的结构太大,RAM中没有成员(只在EEPROM中)。 我想做一些地址计算,但不要定义RAM成员。 我可以使用结构指针而不是结构variables(它只需要4字节),但是这个例子对我来说很有意思。
使用offsetof你可以在成员之间进行计算,而不必掌握该types的variables。 所有你需要的是types本身和成员的名字。
注意为什么简单的计算可能无法解决:数据alignment。 你不知道你的编译器会在你的结构中填充的填充量,如果你改变了结构,这会导致非常微妙的错误,或者使看起来正确的计算错误。
首先,你将单个地址转换为int
。 我不认为这是一个好主意。 一个int
保证至less有2个字节或更多的大小,地址/指针通常是4或8个字节。 把这些int
只是不坐。 如果我把它们投到任何东西,我可能会使用unsigned long
为32位系统, unsigned long long
为64位。 我会使用后者是安全的。
也就是说,我不会投这些地址,只是使用offsetof
macros。
将#include <stddef.h>
添加到文件中,并使用offsetof
macros,将偏移值转换为size_t
types,而不是int
,请注意。 它只需使用0作为结构的内存地址,然后返回给定成员的地址,给出实际的偏移量:
size_t offset = offsetoff(T1, c); //struct, member
正如Zack在他的评论中指出的那样,答案的下一部分有点不相关,但是对于它包含的链接,为了完整起见,我将把它留在这里 – 因为所有实现都需要offsetof
:
自己定义一个macros,如果你没有stddef.h出于某种原因(它应该是这样,因为offsetof
已经在一段时间内成为标准的一部分:C89以上),就像这样:
#ifndef offsetof #define offsetof(s, m) ((size_t)&(((s *) 0)->m)) #endif
这应该做的伎俩,但要小心:这种实现可能会导致未定义的行为。 如何和为什么在这里解释
我已经从我在这里find的stddef.h源文件中获得了上面定义的offsetof
,所以你可以直接下载这个文件,并使用它,而不是在你自己的文件中定义这个macros,但是请记住,你使用的offsetof
量不是100%可靠。
无论如何,现在已经足够了,Google上有更多的信息,但是这里有几个链接:
- GCC文档
- 有关SO的相关问题
- 另一个SO问题
您可以使用stddef.h
定义的offsetof
。
我知道这超出了你所问的范围,但在linux内核代码container_of
macros中有一个有用的offsetof
。 container_of
可以返回父结构的地址,给出一个指向其成员的指针:
#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
你可以使用例如:
// pointer_to_c points to a member of the struct, c in this case // and you want to get the address of the container T1 *container; container = container_of(pointer_to_c, T1, c);
stddef.h
有一个名为offsetof的macros,它给出了一个结构起始位置的偏移量。
size_t t = offsetof( T1 , c ) ;
这样你就不必实际声明任何结构variables。
看看数据结构alignment
这是正确的:
size_t dist = offsetof(struct _s1, c);
在头文件stddef.h
有一个macros; offsetof
。 你可以像这样在你的结构体上使用它:
int dist = (int)offsetof(T1, c);