我有以下程序:
#include <iostream>
struct X
{
int a;
float b;
} x[10], *p1, *p2;
int main(int argc, char *argv[])
{
p1 = &x[1];
p2 = &x[5];
int i = p2 - p1;
std::cout << i << std::endl;
}
我可以想象 X
在内存中的布局,10 个盒子包含一个 int
和一个 float
,p1
将指向第二个框的开头 (x[1]
) 和 p2
指向第 6 个框的开头 (x[5]
):
X 0 1 2 3 4 5 6 7 8 9
_______________________________
b |__|__|__|__|__|__|__|__|__|__|
a |__|__|__|__|__|__|__|__|__|__|
| |
| |
p1 p2
我画的对吗?如果是这样,为什么 i
的结果是 4 ?
在理解两个地址的减法时遇到一些困难?
最佳答案
这就是pointer arithmetic作品。考虑:
p1 = (x*)100; // invalid memory address, just an example!
p2 = p1 + 1;
此时,p2
的值将不是 101
,而是 100 + sizeof(x)
(假设为 8 , 所以 108).它不是增加了 1,而是增加了 sizeof(x)
的倍数!相反,从指针中减去一个整数实际上减去 sizeof(指向的类型)
的倍数。
所以现在如果你执行 int diff = p2 - p1
,你肯定会期望得到 1
,而不是 8
!否则,减去刚刚添加的数字将不会产生原始值。因此,从一个指针中减去另一个指针得到的不是内存地址的差异,而是两个指针之间的元素数量。
此外,标准要求指针减法是没有意义的,除非两个指针指向同一数组中的元素(更准确地说,这是未定义的行为,您也可以使用指向“一个”的指针超过最后一个元素”,即使那里没有这样的对象)。
最后,如果编译器不知道指向类型的大小(即指针是 void*
)怎么办?在这种情况下,根本不允许指针运算。例如:
void* p = 100;
void* x = p + 1; // does not compile¹
¹ 某些编译器可能会在 void*
上提供指针算法作为 extension到语言规范。在这种情况下,该语句确实可以编译,结果将取决于所述扩展的规范(例如,gcc 将以值 101 结束)。
关于c++ - 当我减去内存地址时,为什么结果比我预期的要小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8357151/