当我们 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
因为这样做你 分配一个address 到 q
它需要但重点是它不是有效地址,因此当你做 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;
}
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
因为这样做你 分配一个address 到 q
它需要但重点是它不是有效地址,因此当你做 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;
}