这种指针标记方法是否符合C标准?

Leu*_*nko 11 c standards-compliance

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

对我之前关于这个主题的问题的一个很好的答案证实,将指针转换为整数和对整数进行处理的天真方法在技术上无法依赖于工作(无视其在实践中的受欢迎程度).

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

// 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]
Run Code Online (Sandbox Code Playgroud)

用语言:没有关于指针的整数表示的假设.通过索引指向对象内的字节来应用标记.(这当然是允许的.)

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

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

(不,我不知道为什么这种技术性在我脑海中浮现如此;是的,可移植性很容易通过其他方式实现.)

Jen*_*edt 5

在这里,我认为你唯一需要更加小心的是你的整数类型.不要使用int:

  • 指针差异的正确类型是ptrdiff_t.
  • 结果sizeofsize_t无符号类型
  • %size_t类型之间做,ptrdiff_t所以结果很可能size_t,所以一个无符号的值
  • 转换该size_tint是定义(因此不是便携式的)实施方式中,通常它只是丢弃该高位比特

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