![](/img/trans.png)
[英]Is there ANY way to compare two void pointers to assert the same type in C?
[英]C: what type is the difference of two void pointers?
如果我减去两个空指针,我将得到两个指针位置之间的相对距离(以字节为单位)(至少在我的测试系统上)。 我应该使用哪种类型来存储结果,以使其与64位系统兼容? size_t是正确的类型还是长的?
背景:我们需要检查给定的void指针用作双指针是否安全。 我们曾经将指针强制转换为int并检查低三位是否为零,但是我们目前的编码标准不再允许将指针强制转换为整数类型。 我正在考虑计算void指针和NULL指针之间的差异,并检查该差异是否可被8除。假设NULL指针始终是8字节对齐的?
空指针的减法未在C标准中定义。 仅当指针都指向同一个数组并且void指针不能指向任何数组时才定义指针减法,因为您不能拥有包含void元素的数组。
很可能您正在使用gcc或兼容的东西,并且它允许对void指针进行算术运算,并将其作为char指针的扩展。 但是严格的C编译器不应允许对void指针进行指针运算。
从C11, 6.5.6 Additive operators /9
(我的斜体):
当减去两个指针时,两个指针都将指向同一数组对象的元素,或者指向数组对象的最后一个元素之后的元素; 结果是两个数组元素的下标不同。 结果的大小是实现定义的, 其类型(带符号整数类型)是在
<stddef.h>
标头中定义的ptrdiff_t
。
在该部分中,从指针中减去NULL在技术上也是未定义的行为,因为绝对不能将NULL
视为指向同一数组或该数组之外元素的指针。 指针减法实际上仅限于获得同一数组中两个元素之间的索引差。
因此,您可能想重新考虑一下您正在执行的检查,尤其是考虑到双精度实际上不需要八字节长的事实,即使是这样,标准中也没有要求将其对齐一个八字节的边界。
我更倾向于只是在函数的文档中指出,传递的值必须是有效的double
指针,并且,如果函数的用户违反了该合同,则所有押注均无效。
如果我减去两个空指针,我将得到两个指针位置之间的相对距离(以字节为单位)(至少在我的测试系统上)。
有一个严格的规则减去两个指针。 C11-§6.5.6:
当减去两个指针时,两个指针都将指向同一数组对象的元素,或者指向数组对象的最后一个元素之后的元素; 结果是两个数组元素的下标不同。 [...]
两个void指针的区别是什么类型?
应该是ptrdiff_t
。
[...]结果的大小是实现定义的,其类型(有符号整数类型)是在
<stddef.h>
标头中定义的ptrdiff_t
。 [...]
问题摘要:
您正在将空指针常量宏NULL与空指针混淆。 那是两个不同的术语。 NULL宏始终等于0,但是空指针可以具有任何值。 看到这个 。
话虽如此,使用空指针或NULL宏进行指针算术没有任何意义。 这样做会调用未定义的行为,因为指针必须指向同一数组。 请参阅paxdiablo的答案。
此外,如Art的答案所述,您不能对void指针进行任何形式的算术运算。 +和-运算符指定为(6.5.6):
另外,两个操作数都应具有算术类型,或者一个操作数应是指向完整对象类型的指针,另一个操作数应具有整数类型。
空指针是指向不完整类型的指针,因此,如果一个或两个操作数都是空指针,则您的代码无效C。
请注意,GCC具有非标准扩展名,允许通过将空指针视为此类情况的字节指针来进行空指针算术运算。 如果要编写安全且可移植的程序,请不要使用此非标准功能。 如果希望GCC充当标准C编译器(符合实现),则使用gcc -std=c11 -pedantic-errors
进行编译。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.