C:做sizeof的更好方法(((SomeStruct *)0) - > some_member)?

时间:2009-06-18 19:37:45

标签: c ffi

我想获得结构中特定成员的大小。

sizeof(((SomeStruct *) 0)->some_member)对我有用,但我觉得可能有更好的方法。

我可以#define SIZEOF_ELEM(STRUCT, ELEM) sizeof(((STRUCT *) 0)->ELEM)然后使用SIZEOF_ELEM(SomeStruct, some_member),但我想知道是否已经有更好的内置功能。<​​/ p>

我的具体用例是hsc2hs(Haskell C绑定)。

pokeArray (plusPtr context (#offset AVFormatContext, filename)) .
  take (#size ((AVFormatContext *) 0)->filename) .
  (++ repeat '\NUL') $ filename

4 个答案:

答案 0 :(得分:5)

如果你不能保证你有一个变量可以取消引用,那么你得到的就是干净利落。 (如果可以,那么当然只使用sizeof(var.member)sizeof(ptr->member),但这在需要编译时常量的某些上下文中不起作用。)

很久很久以前(大约1990年),我遇到了一个使用基地址0定义了'offsetof'的编译器,它崩溃了。我通过攻击<stddef.h>来解决这个问题,使用1024而不是0。但是你现在不应该遇到这样的问题。

答案 1 :(得分:3)

我相信你已经有了正确的解决方案。您可以挖掘stddef.h并查找offsetof的定义方式,因为它的确非常类似。

请记住,由于填充,成员的大小与该成员的offsetofs与下一个成员的offsetof之间可能存在差异。

答案 2 :(得分:3)

在C ++中,您可以执行sizeof(SomeStruct :: some_member),但这是c并且您没有范围解析运算符。据我所知,你所写的内容与所写的一样好。

答案 3 :(得分:3)

Microsoft在其标题之一中包含以下内容:

#define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field))

我认为没有理由做任何不同。

他们有相关的宏:

RTL_SIZEOF_THROUGH_FIELD()
RTL_CONTAINS_FIELD()

和漂亮的:

CONTAINING_RECORD() 

有助于在直接C中实现通用列表,而不必要求链接字段位于结构的开头。有关详细信息,请参阅此Kernel Mustard article