【问题标题】:Why offsetof returns a size_t instead of an uintptr_t?为什么 offsetof 返回 size_t 而不是 uintptr_t?
【发布时间】:2017-03-28 09:28:39
【问题描述】:

我注意到我的 offsetof 实现:

#define offsetof(st, m) ((size_t)&(((st *)0)->m))

返回一个size_t,但我认为它应该是uintptr_t,因为offsetof 的值最有可能用于增加一个指针。

我有这个功能:

int flash_seek(intptr_t offset32, int whence);

它将 FLASH 的内部指针移动到另一个位置。所以offset32 是一个偏移量。如果我想将指针从结构的偏移量中移出:

flash_seek(offsetof(foo_t, bar), SEEK_CUR);

我收到警告,因为 uintptr_tsize_t 的类型不同。如果我不想添加演员表,我应该如何纠正这个问题?

【问题讨论】:

  • 也许是你的函数有错误的签名:-)
  • size_t 是计数类型,uintptr_t 是位置类型。 offsetof 返回后者是没有意义的,不管它是如何实现的。
  • 如果在 POSIX 上并且您在文件偏移后使用 off_t 定义为 <fcntl.h> / <sys/types.h>
  • 附带说明:您似乎正在使用结构在闪存上存储/读取数据。这不像进行适当的序列化那样可扩展。每当您需要使用offsetof 时,您应该重新考虑您的设计。旨在尽量减少对结构布局的依赖。
  • uintptr_t 是一种用于指针转换的类型,而不是算术类型。如果您想将偏移量视为地址的差异,您应该使用prtrdiff_t

标签: c pointers c99


【解决方案1】:

size_t 是一个无符号整数类型,可以容纳系统上最大对象的大小。

这使它成为保存可能是系统上最大结构中最后一个成员的偏移量的完美候选者。

它也需要在任何符合 C 标准库的实现上定义。 uintptr_t 是可选的。

uintptr_t 还设计用于保存转换为整数值的地址。它是保存一个绝对位置,而不是与某个未指定位置的偏移量。此外,该标准对如何完成address->integral value->address 之间的映射没有任何要求。只要求两端地址相同。

为什么的答案主要归结为size_tuintptr_t是完全不同事物的抽象,前者是需要定义的。 p>

【讨论】:

  • 关于uintptr_t 的另一点是它只保证保存指针的整数转换。 C 标准在任何地方都没有保证指针必须是整数,只有转换为整数然后再返回才能保存值。
  • @JeremyP:标准是否真的保证将指针转换为整数并返回保存值,或者只保证它产生一个与原始值比较等于的指针?指针可能比较相等,但无法访问相同的对象(“刚刚过去的”指针可能与指向对象的指针比较相等,但只能用于访问前面的对象);标准没有说明重铸的 uintptr_t 是否可以以任何方式使用它比较等于的相同类型指针。
  • @supercat 该标准不保证将指针转换为整数是可能的。两个方向的行为都是“实现定义的”。但是,它确实保证,如果 uintptr_t 存在,您可以将 void* 投射到它并再次返回,结果将比较相等,这与具有相同值相同。如果不是“具有相同的值”,“相等”是什么意思?
  • @JeremyP:说两个指针“比较相等”意味着将==运算符应用于它们将产生1。编译器可能会假设给定int a1[1],a2[1],*p1=a1+5,*p2=a2,x,y;,即使p1和@987654333 @碰巧比较相等,对p1[x]的操作只能影响a1,对p2[x]的操作只能影响a2。如果p1p2被转换为void*,那么uintptr_t,然后一个具有相同数值的uintptr_t被转换为void*,又回到int* p3,不清楚是否@987654345 @ 可以访问a2[0]p3[-1] 可以访问a1[0],两者都可以访问,或者都不访问。
  • @JeremyP:如果将void* 以外的类型的指针转​​换为uintptr_t 或反之亦然,它的含义也不清楚。如果这样的结构没有意义,标准就没有理由在语法上允许它。在大多数系统上,没有合理的理由让它的行为不同于 void*,然后是 uintptr_t,反之亦然,但是编译器做了很多没有合理理由的事情。
猜你喜欢
  • 1970-01-01
  • 2011-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-02
  • 2021-09-13
  • 2017-06-30
  • 1970-01-01
相关资源
最近更新 更多