c++ - 当我减去内存地址时,为什么结果比我预期的要小?

标签 c++ c

我有以下程序:

#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 和一个 floatp1 将指向第二个框的开头 (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/

相关文章:

c++ - QGraphicsView 中的事件

c++ - union 和内存对齐的问题

C 函数返回分配给非常量指针的常量指针 - 警告不是错误

c - 什么是适合与 LPC1788 微 Controller 一起使用的 RTOS?

c - 在 OpenCL 中切片字符串

c - 为什么我们不在 TCP 程序中使用客户端地址?

c++ - 如何检查用户是否输入?

c++ - 如何使用 C++ 显示 "Loading..."并使用 3 个点进行动画处理?

c++ - 创建嵌套类的实例

c++ - 如何在调整大小时保持相同的场景部分可见?