为什么我不能用C++中的不同指针访问int?

问题描述:

我希望能够用p指针访问值。但是当我使用p指针时,我总是得到等于零的b变量。请参阅下面的代码片段。为什么我不能用C++中的不同指针访问int?

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指针访问值?

+1

尝试'*(int *)(basepointer + 32)= 455;'而不是第二行。然后去阅读指针算术。 – aragaer

+1

@aragaer如果'basepointer'的类型为'void *',这不是个好主意。 – aschepler

+0

basepointer的类型是什么? – Bathsheba

我不能找到一个很好的答案重复,所以这里发生了什么:

指针运算总是在指针的基本类型的单位发生。也就是说,当您有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后第32nd int的地址。如果您的平台使用4字节整数,则实际偏移量为32 * 4 = 128字节。这是我们存放455的地方。

然后你做

void *p = basepointer + 32; 

这在技术上是无效的代码,因为basepointer是一个void *,你不能在void方面做算术题,因为void没有大小。作为扩展,gcc支持这个并假装void具有大小1

现在pbasepointer抵销后32:(如果你想按字节寻址投地unsigned char *但你真的不应该依赖于这一点。)。

a = *((int*)basepointer+32); 

这从上方重复指针算术和检索来自int偏移32的值(即字节偏移128),这仍然是455

b = *((int*)p); 

此检索存储在字节int值偏移32(其将对应于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

0地址

如果编译器允许,则为1