繁体   English   中英

C:两个void指针的区别是什么?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM