【问题标题】:Is this method of pointer tagging in C standard-compliant?这种 C 标准中的指针标记方法是否符合标准?
【发布时间】:2013-12-17 10:02:29
【问题描述】:

(回顾指针标记:对象的大小意味着其指针中的有限数量的位将始终未使用,并且可以重新用于其他用途,例如标记对象的类型。)

excellent answer 到我的previous question 在这个主题上证实,将指针转换为整数并处理这些整数的幼稚方法在技术上不能依赖于工作(不管它在实践中的流行程度)。

再想一想,我想我有一个适用于原始问题中描述的特定情况的解决方案(所有对象的大小相同,所有对象都是从单个“堆”数组分配的)。有人可以证实我的推理吗?

// given:
typedef Cell ...; // such that sizeof(Cell) == 8
Cell heap[1024];  // or dynamic, w/e

// then:
void * tagged = ((char *)&heap[42]) + 3;  // pointer with tag 3 (w/e that means)

int tag = ((char *)tagged - (char *)heap) % sizeof(Cell);  // 3
Cell * ptr = (Cell *)((char *)tagged - tag);               // &heap[42]

换句话说:没有关于指针的整数表示的假设。通过对指向对象中的字节进行索引来应用标签。 (这当然是允许的。)

指针减法返回同一数组中两个对象的索引差。对象中的字节地址应该是连续的,因此通过获取寻址字节的索引并从该索引中删除所有前面单元格的大小,将标记值转换为标记;标记指针可以通过删除现在已知的索引偏移量恢复为 Cell 指针。

这一切都符合标准,因此是一种可移植的指针标记方法吗?如果数组的类型转换为其他类型(在这种情况下为 char),是否仍然允许指针减法工作?我可以这样使用sizeof(Cell)吗?

(不,我不知道为什么这种技术性如此困扰我;是的,可移植性很容易通过其他方式实现。)

【问题讨论】:

  • 据我所知,是的,这是有效的、可移植的 C。但是我没有任何论据,除了没有任何禁止它的文本,所以我发布了这个作为评论而不是答案。希望其他人可以填写一些细节。

标签: c standards-compliance


【解决方案1】:

我认为你必须更加小心的唯一事情是你的整数类型。不要使用int

  • 指针差异的正确类型是ptrdiff_t
  • sizeof 的结果是 size_t 无符号类型
  • 您在size_t 类型和ptrdiff_t 之间执行%,所以结果很可能是size_t,所以是一个无符号值
  • size_t 转换为 int 是实现定义的(因此不可移植),通常它只会丢弃高位

int 可以工作很长时间,但是当你在 64 位处理器上使用一个非常大的数组时,你会后悔的(经过几天的调试)

【讨论】:

    猜你喜欢
    • 2011-10-31
    • 2016-12-03
    • 2016-06-02
    • 2012-10-28
    • 1970-01-01
    • 2021-04-26
    • 2011-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多