C:更好的方法来执行 sizeof(((SomeStruct *) 0)->some_member)?
题
我想获取结构中特定成员的大小。
sizeof(((SomeStruct *) 0)->some_member)
对我有用,但我觉得可能有更好的方法。
我可以 #define SIZEOF_ELEM(STRUCT, ELEM) sizeof(((STRUCT *) 0)->ELEM)
然后使用 SIZEOF_ELEM(SomeStruct, some_member)
, ,但我想知道是否已经有更好的内置东西。
我的具体用例是 hsc2hs(Haskell C 绑定)。
pokeArray (plusPtr context (#offset AVFormatContext, filename)) .
take (#size ((AVFormatContext *) 0)->filename) .
(++ repeat '\NUL') $ filename
解决方案
如果您不能保证有一个变量可以取消引用,那么您所得到的就是尽可能干净。(如果可以的话,只使用 sizeof(var.member)
或者 sizeof(ptr->member)
, 当然,但这在某些需要编译时常量的上下文中不起作用。)
很久很久以前(大约 1990 年),我遇到了一个编译器,它有 'offsetof
' 使用基地址 0 定义,结果崩溃了。我通过黑客解决了这个问题 <stddef.h>
使用 1024 而不是 0。但你现在不应该遇到这样的问题。
其他提示
我相信您已经找到了正确的解决方案。您可以挖掘 stddef.h 并查找 offsetof 是如何定义的,因为它做了非常相似的事情。
请记住,由于填充的原因,某个成员的大小以及该成员与下一个成员的偏移量之间很可能存在差异。
在 C++ 中,您可以执行 sizeof(SomeStruct::some_member),但这是 c 并且您没有范围解析运算符。据我所知,你写的已经是最好的了。
Microsoft 在其标头之一中包含以下内容:
#define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
我认为没有理由采取任何不同的做法。
他们有相关的宏:
RTL_SIZEOF_THROUGH_FIELD()
RTL_CONTAINS_FIELD()
和俏皮的:
CONTAINING_RECORD()
这有助于在直接 C 中实现通用列表,而无需要求链接字段位于结构的开头。看到这个 芥末仁文章 了解详情。