有没有一种方法可以在 C11 中将一个指针与另一个指针相减,并始终定义结果?
该标准规定,如果结果不能表示为 ptrdiff_t 类型,则行为未定义。
我对依赖于静态断言的解决方案持开放态度,该解决方案有望在现代通用 32 或 64 位环境中传递合理的实现。我想避免依赖任何类型的运行时检查的解决方案。
如果指向的类型的大小大于 1,我可以静态断言 size_t 和 ptrdiff_t 具有相同数量的非填充位。这个部分解决方案依赖于我不确定的两件事,因此任何对此的反馈都将提供部分答案:
可以预期,在现代通用 32 或 64 位环境中的合理实现中,ptrdiff_t 至多比 size_t 少一位值位。
我对标准的理解是正确的,因为两个指向大小大于 1 的对象的指针之间的差异是定义的,即使如果指针被转换为字符指针,相同的差异将是未定义的。这种理解似乎与委员会草案中的脚注106不一致,但我的理解是脚注不具有规范性。
根据标准
仅当两个指针都指向同一对象(其中包括“最后一位”指针)时,才可以对指针进行减法。
减法uintptr_t
or intptr_t
不一定有意义,因为根据标准,没有必须定义从指针到整数的转换的特定方法。尤其,
因此,不幸的是,根据标准,没有办法可移植地做到这一点。
记住: size_t
是物体的最大尺寸。这是not地址空间的大小。这是完全合法的size_t
范围更小uintptr_t
和朋友。与相同ptrdiff_t
: 这是完全合法的ptrdiff_t
范围小于uintptr_t
。例如,想象一下分段内存模型,您无法分配大于段的任何内容,在这种情况下,size_t
and ptrdiff_t
可能能够表示段的大小,但不能表示地址空间的大小。
根据实践
在您使用的计算机(现代 32 位和 64 位计算机)上,uintptr_t
仅包含指针地址。减去掉。这是实现定义的但不是未定义的行为。
不要在不进行强制转换的情况下减去原始指针,除非它们指向同一个对象,或者指向该对象之后的地址。当您使用指针算术时,编译器可以并且将会做出别名假设。不仅你的程序在“技术上”是错误的,而且编译器在这里产生错误代码的历史也很长。
关于指针指向同一个对象到底意味着什么,现在存在一些争论,但我上次检查时这个争论尚未解决。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)