为什么我不能在 C++ 中使用不同的指针访问 int?
Why can't I access int with different pointer in C++?
我希望能够使用 p 指针访问值。但是当我使用 p 指针时,我总是让 b 变量等于零。请参考下面的代码片段。
basepointer = malloc(512);
*((int*)basepointer+32) = 455; // putting int value in memory
void *p = basepointer + 32; // creating other pointer
int a,b;
a = *((int*)basepointer+32); // 455, retrieving value using basepointer
b = *((int*)p); // 0, retrieving value using p
为什么会这样?如何使用我的 p 指针访问值?
我找不到一个好的重复答案,所以这是发生了什么:
指针运算总是以指针的基类型为单位进行。也就是说,当你有 T *ptr
(指向某种类型 T
的指针)时,那么 ptr + 1
不是内存中的下一个字节,而是下一个 T
.
换句话说,你可以把指针想象成数组和索引的组合:
T *ptr;
T array[/*some size*/];
ptr = &array[n];
如果ptr
是指向array[n]
(第n个元素)的指针,那么ptr + i
是指向array[n + i]
(第(n+i)个元素)的指针).
让我们看一下您的代码:
*((int*)basepointer+32) = 455;
此处您将 basepointer
转换为 (int*)
,然后向其添加 32
。这为您提供了 basepointer
之后第 32 个 int
的地址。如果您的平台使用 4 字节整数,则实际偏移量为 32 * 4 = 128
字节。这是我们存储 455
.
的地方
然后你做
void *p = basepointer + 32;
这在技术上是无效的代码,因为 basepointer
是一个 void *
,并且您不能根据 void
进行算术运算,因为 void
没有大小。作为扩展,gcc 支持这个并假装 void
的大小为 1
。 (但是你真的不应该依赖这个:如果你想要按字节寻址,则转换为 unsigned char *
。)
现在 p
在 basepointer
之后的偏移量 32
。
a = *((int*)basepointer+32);
这会重复上面的指针运算,并从 int
偏移量 32(即字节偏移量 128
)中检索值,它仍然是 455
.
b = *((int*)p);
这将检索存储在字节偏移量 32
处的 int
值(在本例中对应于 int
偏移量 8
)。我们从来没有在这里存储任何东西,所以 b
本质上是垃圾(在你的平台上恰好是 0
)。
使此代码按预期工作的最小更改可能是
void *p = (int *)basepointer + 32; // use int-wise arithmetic to compute p
无效指针算法在C/C++中是非法的,GCC允许它作为扩展。
你需要修改这一行:
void *p = basepointer + 32;
到
void *p = basepointer + 32 * sizeof(int);
因为指针算法是相对于类型大小计算的。
例如:
如果sizeof (int) = 4
和 sizeof(short) = 2
和int *p
的地址为3000
short *sp
的地址为 4000
然后 p + 3 = p + 3 * sizeof(int) = 3012
和 sp + 3 = sp + 3 *sizeof(short) = 4006
对于 void 它是 1
如果编译器允许的话。
我希望能够使用 p 指针访问值。但是当我使用 p 指针时,我总是让 b 变量等于零。请参考下面的代码片段。
basepointer = malloc(512);
*((int*)basepointer+32) = 455; // putting int value in memory
void *p = basepointer + 32; // creating other pointer
int a,b;
a = *((int*)basepointer+32); // 455, retrieving value using basepointer
b = *((int*)p); // 0, retrieving value using p
为什么会这样?如何使用我的 p 指针访问值?
我找不到一个好的重复答案,所以这是发生了什么:
指针运算总是以指针的基类型为单位进行。也就是说,当你有 T *ptr
(指向某种类型 T
的指针)时,那么 ptr + 1
不是内存中的下一个字节,而是下一个 T
.
换句话说,你可以把指针想象成数组和索引的组合:
T *ptr;
T array[/*some size*/];
ptr = &array[n];
如果ptr
是指向array[n]
(第n个元素)的指针,那么ptr + i
是指向array[n + i]
(第(n+i)个元素)的指针).
让我们看一下您的代码:
*((int*)basepointer+32) = 455;
此处您将 basepointer
转换为 (int*)
,然后向其添加 32
。这为您提供了 basepointer
之后第 32 个 int
的地址。如果您的平台使用 4 字节整数,则实际偏移量为 32 * 4 = 128
字节。这是我们存储 455
.
然后你做
void *p = basepointer + 32;
这在技术上是无效的代码,因为 basepointer
是一个 void *
,并且您不能根据 void
进行算术运算,因为 void
没有大小。作为扩展,gcc 支持这个并假装 void
的大小为 1
。 (但是你真的不应该依赖这个:如果你想要按字节寻址,则转换为 unsigned char *
。)
现在 p
在 basepointer
之后的偏移量 32
。
a = *((int*)basepointer+32);
这会重复上面的指针运算,并从 int
偏移量 32(即字节偏移量 128
)中检索值,它仍然是 455
.
b = *((int*)p);
这将检索存储在字节偏移量 32
处的 int
值(在本例中对应于 int
偏移量 8
)。我们从来没有在这里存储任何东西,所以 b
本质上是垃圾(在你的平台上恰好是 0
)。
使此代码按预期工作的最小更改可能是
void *p = (int *)basepointer + 32; // use int-wise arithmetic to compute p
无效指针算法在C/C++中是非法的,GCC允许它作为扩展。
你需要修改这一行:
void *p = basepointer + 32;
到
void *p = basepointer + 32 * sizeof(int);
因为指针算法是相对于类型大小计算的。
例如:
如果sizeof (int) = 4
和 sizeof(short) = 2
和int *p
的地址为3000
short *sp
的地址为 4000
然后 p + 3 = p + 3 * sizeof(int) = 3012
和 sp + 3 = sp + 3 *sizeof(short) = 4006
对于 void 它是 1
如果编译器允许的话。