没有结构对象的C指针算术

时间:2014-01-30 11:35:06

标签: c++ c pointers math

我认为在C中不可能,但要求验证这一点。是否可以在没有这种类型的实变量的结构成员之间进行算术运算?例如:

typedef struct _s1
{
  int a;
  int b;
  int c;
} T1;

我希望看到“c”成员与结构开始的偏移量。如果我有变量很容易:

T1 str;

int dist = (int)&str.c - (int)&str;

但是我的结构太大而且RAM中没有成员(仅在EEPROM中)。我想做一些地址计算,但不想定义RAM成员。我可以使用结构指针而不是结构变量(它只需要4个字节)来完成工作,但这个案例对我来说很有意思。

6 个答案:

答案 0 :(得分:57)

使用offsetof,您可以在成员之间进行计算,而无需获取该类型的变量。您只需要类型本身和成员的名称。

注意为什么简单计算可能无法解决:数据对齐。您不知道编译器将在您的结构中抛出的填充量,如果更改结构,这可能会导致非常微妙的错误或使看似正确的计算错误。

答案 1 :(得分:25)

首先,您将个别地址转换为int。我认为这不是一个好主意。保证int的大小至少为 2 字节或更大,地址/指针通常为4或8字节。将这些转换为int并不恰到好处。如果我将它们转换为任何东西,我可能会将unsigned long用于32位系统,将unsigned long long用于64位。我会用后者来保证安全 也就是说,我根本不会转发地址,只使用offsetof宏。

#include <stddef.h>添加到您的文件中,并使用offsetof宏,将偏移值转换为size_t类型,而不是int,请注意。它只使用0作为结构的内存地址,然后返回给定成员的地址,给出实际的偏移量:

size_t offset = offsetoff(T1, c);
                    //struct, member

正如扎克在评论中指出的那样,答案的下一部分有点无关紧要,但对于它所包含的链接,为了完整起见,我将把它留在这里 - 因为offsetof是必需的所有实现:

如果由于某种原因没有stddef.h,那么自己定义一下宏(应该是这样,因为offsetof已经成为标准的一部分了一段时间:C89及以上),就像这样:

#ifndef offsetof
#define offsetof(s, m) ((size_t)&(((s *) 0)->m))
#endif

应该这样做,但要小心:这种实现可能会导致未定义的行为。 How and why is explained here
我从the stddef.h source I found here获取了上面的offsetof定义,因此您可以下载该文件并使用它,而不是在您自己的文件中定义宏,但请记住{{1}你使用不是100%可靠。

无论如何,现在已经足够了,谷歌有更多信息,但这里有几个链接:

答案 2 :(得分:16)

您可以使用offsetof中定义的stddef.h

我知道这超出了你的要求,但是在Linux内核代码offsetof宏中有一个有用的container_of用法。 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);

答案 3 :(得分:12)

stddef.h有一个名为offsetof的宏,它给出了一个成员从结构开头的偏移量。

size_t t = offsetof( T1 , c ) ;

这样您就不必实际声明任何结构变量。

答案 4 :(得分:10)

看看Data structure alignment

这是正确的:

size_t dist = offsetof(struct _s1, c);

答案 5 :(得分:8)

标题stddef.h中有一个宏; offsetof。您可以在结构上使用它,如下所示:

int dist = (int)offsetof(T1, c);