C中指针减法期间的除法

时间:2018-12-05 19:48:05

标签: c pointers pointer-arithmetic

请考虑以下代码段:

int *p;
/* Lets say p points to address 100 
   and sizeof(int) is 4 bytes. */
int *q = p+1;
unsigned long r = q-p;
/* r results in 1, hence for r = q-p 
   something is happening similar to r=(104-100)/4 */

在运行时是否有实际的除以sizeof(datatype)的操作,即减去了两个相同类型的指针,或者还有其他一些机制可以通过这种方式来进行指针减法。

2 个答案:

答案 0 :(得分:3)

C standard声明了有关指针减法的内容(第6.5.6p9节):

  

当减去两个指针时,两个指针都应指向   同一数组对象,或在数组的最后一个元素之后   宾语; 结果是   两个数组元素。结果的大小是   实现定义的,其类型(有符号整数类型)为   标头中定义的ptrdiff_t。如果结果不是   在该类型的对象中可表示的行为是   未定义。换句话说,如果表达式P和Q指向   分别是   -th和j   如果数组对象的第n个元素适合于ptrdiff_t类型的对象,则表达式(P)-(Q)的值为ij。此外,   如果表达式P指向数组对象的元素,或者   在数组对象的最后一个元素之后,还有表达式Q   指向同一数组对象的最后一个元素,即表达式   ((Q)+1)-(P)与((Q)-(P))+ 1具有相同的值   -((P)-((Q)+1)),并且如果表达式P指向数组对象的最后一个元素的偶数,则该表达式的值为零,即使   尽管表达式(Q)+1并不指向数组的元素   宾语。 106)

脚注106指出:

  

另一种处理指针算法的方法是先将   指向字符指针的指针:在此方案中,整数   首先添加到转换指针或从转换指针中减去的表达式   乘以最初指向的对象的大小,   然后将结果指针转换回原始指针   类型。 对于指针相减,求和结果   字符指针之间的距离类似地除以   该对象最初指向的对象。以这种方式查看时,   实现只需要提供一个额外的字节(可能   重叠在程序中的另一个对象之后)   对象,以满足“过去一个元素过去”   要求。

因此脚注指出,可以通过减去原始指针值并除以指向的对象的大小来实现指针减法 。但是,不必以这种方式实现。

还要注意,该标准要求在指向同一数组对象的元素(或末尾的一个元素)的指针之间执行指针减法。如果没有,则行为是不确定的。在实践中,如果您正在使用具有扁平内存模型的系统,则可能仍会获得“期望”值,但您不能依赖它。

答案 1 :(得分:1)

有关指针减法工作原理的说明,请参见@dbush答案。

相反,如果您要编程的是底层代码,例如内核,驱动程序,调试器或类似程序,并且您需要对地址进行实际减法,则将指针转换为char *

(char *)q - (char *)p

结果将为ptrdiff_t类型,即实现定义的带符号整数。

当然,这不是定义的/可移植的C,但是可以在大多数体系结构/环境中使用。