是否有定义的方法在C11中进行指针减法?

Kyl*_*yle 2

有没有办法在C11中从另一个指针中减去一个指针,并且总是定义结果?

如果结果不能表示为类型ptrdiff_t,则标准表示行为未定义.

我对依赖于静态断言的解决方案持开放态度,这些断言有望在现代通用32或64位环境中传递合理的实现.我想避免依赖任何类型的运行时检查的解决方案.

如果指向的类型的大小大于1,我可以静态断言size_t和ptrdiff_t具有相同数量的非填充位.这种局部解决方案依赖于我不确定的两件事,所以对此的任何反馈都会提供部分答案:

  1. 在现代通用32或64位环境中的合理实现中,可以预期ptrdiff_t具有比size_t少至少一个值位.

  2. 我对标准的理解是正确的,因为定义了两个指向大小大于1的对象的指针之间的差异,即使指针被强制转换为字符指针时,也会定义相同的差异.这种理解似乎与委员会草案中的脚注106不一致,但我的理解是脚注不是规范性的.

Die*_*Epp 5

根据标准

如果两个指针指向同一个对象,则只能减去指针,其中包括"一个接一个"的指针.

减去uintptr_tintptr_t不一定有意义,因为同样,根据标准,没有特定的方法必须定义从指针到整数的转换.特别是,

  • 考虑分段内存模型中的远指针,其中可能有多种方式来表示给定地址(段+偏移,例如,在x86上).

  • 考虑具有被处理器忽略的位的指针.(例如,Motorola 68000处理器,它具有32位指针,但前8位被忽略.)

所以,不幸的是,根据标准,没有办法可以做到这一点.

记住: size_t是对象的最大大小.它不是您的地址空间的大小.和朋友一起size_t减少射程是完全合法的uintptr_t.同样ptrdiff_t:缩小ptrdiff_t范围比完全合法uintptr_t.例如,想象一下,在这种情况下,您不能分配大于段的任何内容的分段内存模型,size_t并且ptrdiff_t可能能够表示段的大小,但不能表示地址空间的大小.

根据实践

在您使用的计算机(现代32位和64位计算机)上,a uintptr_t将只包含指针地址.减去.这是实现定义但不是未定义的行为.

除非它们指向同一个对象,或者指向经过该对象的地址,否则不要在不进行强制转换的情况下减去原始指针.当您使用指针算法时,编译器可以并将使用别名假设.您的程序不仅"技术上"错误,而且编译器在此处生成错误代码的历史也很悠久.

现在有一个争论正在进行,关于指向同一个对象的指针究竟是什么意思,但是这个参数在我上次检查时没有得到解决.

  • 一个_very nice_答案. (2认同)