在C标准中,指针的void类型不支持相减运算。只有当两个指针都指向同一个数组时才能进行指针相减,而void指针无法指向任何数组,因为不能创建void元素的数组。
最有可能的情况是您正在使用gcc或类似的编译器,它允许将void指针视为char指针进行算术运算。但是,严格的C编译器不应该允许对void指针进行指针算术运算。
-std=c11 -pedantic-errors
。当您尝试执行非标准操作时,您将会得到编译器错误提示。 - Lundin从C11, 6.5.6加法操作符/9
(我的斜体):
当两个指针相减时,它们都必须指向同一数组对象的元素或该数组对象的最后一个元素之后的一个;结果是两个数组元素下标的差。结果的大小由实现定义,并且其类型(带符号整数类型)是在
<stddef.h>
头文件中定义的ptrdiff_t
。
根据这个部分,从指针中减去NULL也是不确定的行为,因为NULL
无论如何都不能被视为指向同一数组的元素或其中一个元素后面的指针。指针减法真正的限制在于获取同一数组中两个元素之间的索引差异。
因此,您可能需要重新考虑您正在进行的检查,特别是考虑到双精度浮点数实际上并不需要是八个字节长的,即使是八个字节长,标准也没有要求它必须对齐在八字节边界上。
我更倾向于在您函数的文档中声明传递的值需要是有效的double
指针,并且如果您函数的用户违反了这个约定,一切都将不确定。
问题概述:
您混淆了空指针常量宏NULL和空指针。这是两个不同的术语。NULL宏始终等同于0,但空指针可以具有任何值。请参考此处。
话虽如此,使用空指针或NULL宏进行指针算术运算毫无意义。这样做会引发未定义行为,因为指针必须指向相同的数组。请参见paxdiablo的答案。
此外,正如Art的答案中所述,您不能对void指针进行任何形式的算术运算。+和-运算符的规定如下(6.5.6):
对于加法,要么两个操作数都必须具有算术类型,要么一个操作数必须是指向完整对象类型的指针,另一个操作数必须具有整数类型。
void指针是指向不完整类型的指针,因此如果其中一个或两个操作数是void指针,则您的代码无效。
请注意,GCC具有一种非标准扩展,允许对void指针进行算术运算,通过将void指针视为指向字节的指针来处理这种情况。如果您打算编写安全且可移植的程序,请勿使用此非标准功能。如果您希望GCC表现为符合规范的C编译器(符合实现),请使用gcc -std=c11 -pedantic-errors
进行编译。
uintptr_t
,因为我们当前的编码标准不再允许这样做。 - chux - Reinstate Monica