当我们 add/substract 一个整数 from/tp 一个地址时会发生什么

What happens when we add/substract an integer from/tp an address

int m=44;
int* p= & m;    
int* q = p-1    

好的,p 是一个地址,我们如何从中减去 1? q 和 *q

的输出是什么

int m=44;

int* p= & m;

int* q = p-1

这里q指向m之前的block和它的未初始化。 所以 q 会给出 m-sizeof(int) 的地址,*q 会给你 junk(value bw -(2^32)/2 & (2^32)/2 -1)。

C++ 标准在 [expr.add]/4 中对此进行了解释:

When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the expression P points to element x[i] of an array object x with n elements, (...) the expression P - J points to the (possibly-hypothetical) element x[i − j] if 0 ≤ i − j ≤ n; otherwise, the behavior is undefined.

所以在你的例子中,行为是未定义的,因为 p 没有指向数组。

实际上,在大多数主流编译器上,q 只会指向 m 之前的某个内存位置 sizeof(int) 字节。但由于该标准并没有说明太多关​​于内存布局的信息,它可能在任何地方。取消引用 q 可能会导致从垃圾值到段错误或内存损坏的任何类型的奇怪行为。

这个

int m=44;

在 32 位系统上如下所示

       0x103       0x102      0x101       0x100 (lets assume m base address is 0x100)
 ----------------------------------------------
| 0000 0000 | 0000 0000 | 0000 0000 |0010 1100 |
 ----------------------------------------------
                                               m
MSB                                            LSB 

当你喜欢的时候

int *p = &m;    

指针变量p指向m的地址,如下所示

       0x103       0x102      0x101       0x100 
 ----------------------------------------------
| 0000 0000 | 0000 0000 | 0000 0000 |0010 1100 |
 ----------------------------------------------
                                               m
                                               |
                                               p <-- points to 0x100

还有这个

int* q = p-1;    

整数指针被赋值 p-1 无效,如下所示

  0x107.................0x104       0x103       0x102      0x101       0x100 
 ---------------------------------------------------------------------------
 |   un-initialized memory   | 0000 0000 | 0000 0000 | 0000 0000 |0010 1100 |
 ---------------------------------------------------------------------------
                          <--q                                              p

因此,如果您尝试执行 *q,它会尝试从 0x104 开始获取未为 q 保留的数据,导致 分段错误 & 导致 未定义的行为

好的,所以 p 是一个地址,我们如何从中减去 1? 你可以 q = p - 1 因为这样做你 分配一个addressq 它需要但重点是它不是有效地址,因此当你做 q 它崩溃了。例如

int main(void) {
   int m=44;
   int *p = &m;    
   int* q = p-1;
   printf("%p\n",(void*)q); /* this is valid */
   //printf("%d \n",*q); /* this cause seg fault */
   return 0;
}