将 1 添加到地址会导致将 0xE0 添加到该地址
Adding 1 to an address result in adding 0xE0 to that address
我在尝试向使用 &
运算符获得的地址添加偏移量时遇到了一个非常奇怪的行为。
因此,当我尝试向该地址添加任何数字时,结果是该地址加上我的数字乘以 0xE0
(224).
这些是Visual Studio中关注列表的截图。
每张截图的第一行是我的对象地址的访问,是正确的。
第二行是相同的访问,但我们向其添加了变量偏移量。
第三行只是偏移量本身。
如您所见,第一个屏幕截图上的一切都很好。但是在第二个上,加法是 0xE0
(0xE38-0xD58=0x0E0
) 而不是应该的 1 。在最后一张截图中添加的是 0x1C0
即 2*0xE0
.
在第 2 行,我希望在第一个屏幕截图中看到 0x00000255ef9bed58
,在第二个屏幕截图中看到 0x00000255ef9bed59
,在最后一个屏幕截图中看到 0x00000255ef9bed5a
。
给定 t *my_ptr = get_a_pointer_somehow();
和 int my_num = get_a_number_somehow();
,当您执行 my_ptr += my_num
时,它将指针前进 t
的 my_num
,或者换句话说,添加my_num * sizeof(t)
字节。如果您不想要这种行为,则首先将指针转换为 char *
,因为 sizeof(char)
始终为 1。
指针不是整数。指针运算不同于整数运算。向指针加 1 并不意味着 "give me the neighboring address"。指针加 1 表示 "give me the address of the neighbouring object within the array"。相邻物体之间的距离与物体的大小相同。如果该大小大于一个字节,则相邻对象相距几个字节。
在这种情况下,如果您的计算正确,则指向的对象的大小为 0xE0 字节。
要理解这一点,请先编译并运行以下代码(C++,但如果您想使用该语言,我已将 C 行作为注释包括在内):
#include <iostream> // #include <stdio.h>
int main() { // int main(void) {
int xyzzy[2];
int *pXyzzy = &xyzzy[0];
std::cout << pXyzzy << '\n'; // printf("%p\n", pXyzzy);
pXyzzy = pXyzzy + 1;
std::cout << pXyzzy << '\n'; // printf("%p\n", pXyzzy);
return 0;
}
其输出类似于(添加了我的评论):
0x7fffc9ef1150
0x7fffc9ef1154 // four bytes on
尽管您所做的只是将 one 添加到两个输出之间的地址,但这是四个字节的 clear 差异。
那是因为指针算法是根据你指向的东西的大小缩放的。换句话说,加一不会加一个字节,它会加X
字节,其中 X
是(在本例中)4
,int
.
的大小
在您的调试器会话中发生了完全相同的事情,因为如果编译器和调试器不同意表达式的计算方式,这将令人不安(并且调试起来相当痛苦)。如果您要打印出要添加一个的结构的大小,您会发现它是 0xe0
字节长。
如果你真的想要添加一个字节,你需要告诉编译器把它当作大小为1的东西字节,类似于:
pXyzzy = (int*)((char*)pXyzzy + 1);
这导致:
0x7fffdbd74000
0x7fffdbd74001 // one byte on
我在尝试向使用 &
运算符获得的地址添加偏移量时遇到了一个非常奇怪的行为。
因此,当我尝试向该地址添加任何数字时,结果是该地址加上我的数字乘以 0xE0
(224).
这些是Visual Studio中关注列表的截图。 每张截图的第一行是我的对象地址的访问,是正确的。 第二行是相同的访问,但我们向其添加了变量偏移量。 第三行只是偏移量本身。
如您所见,第一个屏幕截图上的一切都很好。但是在第二个上,加法是 0xE0
(0xE38-0xD58=0x0E0
) 而不是应该的 1 。在最后一张截图中添加的是 0x1C0
即 2*0xE0
.
在第 2 行,我希望在第一个屏幕截图中看到 0x00000255ef9bed58
,在第二个屏幕截图中看到 0x00000255ef9bed59
,在最后一个屏幕截图中看到 0x00000255ef9bed5a
。
给定 t *my_ptr = get_a_pointer_somehow();
和 int my_num = get_a_number_somehow();
,当您执行 my_ptr += my_num
时,它将指针前进 t
的 my_num
,或者换句话说,添加my_num * sizeof(t)
字节。如果您不想要这种行为,则首先将指针转换为 char *
,因为 sizeof(char)
始终为 1。
指针不是整数。指针运算不同于整数运算。向指针加 1 并不意味着 "give me the neighboring address"。指针加 1 表示 "give me the address of the neighbouring object within the array"。相邻物体之间的距离与物体的大小相同。如果该大小大于一个字节,则相邻对象相距几个字节。
在这种情况下,如果您的计算正确,则指向的对象的大小为 0xE0 字节。
要理解这一点,请先编译并运行以下代码(C++,但如果您想使用该语言,我已将 C 行作为注释包括在内):
#include <iostream> // #include <stdio.h>
int main() { // int main(void) {
int xyzzy[2];
int *pXyzzy = &xyzzy[0];
std::cout << pXyzzy << '\n'; // printf("%p\n", pXyzzy);
pXyzzy = pXyzzy + 1;
std::cout << pXyzzy << '\n'; // printf("%p\n", pXyzzy);
return 0;
}
其输出类似于(添加了我的评论):
0x7fffc9ef1150
0x7fffc9ef1154 // four bytes on
尽管您所做的只是将 one 添加到两个输出之间的地址,但这是四个字节的 clear 差异。
那是因为指针算法是根据你指向的东西的大小缩放的。换句话说,加一不会加一个字节,它会加X
字节,其中 X
是(在本例中)4
,int
.
在您的调试器会话中发生了完全相同的事情,因为如果编译器和调试器不同意表达式的计算方式,这将令人不安(并且调试起来相当痛苦)。如果您要打印出要添加一个的结构的大小,您会发现它是 0xe0
字节长。
如果你真的想要添加一个字节,你需要告诉编译器把它当作大小为1的东西字节,类似于:
pXyzzy = (int*)((char*)pXyzzy + 1);
这导致:
0x7fffdbd74000
0x7fffdbd74001 // one byte on