好的,所以在一次测试中,我问了这个问题:
int* ptrA; // assigned memory address 100
int a = 1; // assigned memory address 600
ptrA = &a;
What is the memory address of ptrA + 2?
我以为是 606 (int
是 4 个字节 + 地址a
是 600 + 2 = 606 但显然答案是 608,我错过了什么才能做到这一点?
这是未定义的行为,表达式PtrA + 2
是非法的。您只能对您拥有的指针进行指针运算,并且不能添加或减去您拥有的数组范围之外的指针或超出范围的指针。
但是,我们仍然可以对此进行分析(尽管无用,因为 UB)。您假设的地址a
是600 + 2
,但它不是,因为可能sizeof(int*)
也是4
,所以这变成了600 + 4
。所以你得到600 + 4 + 4 = 608
.
实际上指针的算术运算是不同的。它们的增加取决于数据类型的大小,所以如果给定一个地址说 x 并且你必须要求 x+ 2 ..(给定 x 是一个整数指针)然后..
x+ 2 表示 ---- x + (sizeof(int))*2
如果 x 以 char 指针的形式给出,则
x+2 表示 ---- x + (sizeof(char))*2
谢谢。
在 C 语言中,x + y
where x
is 指针等价于&x[y]
. 假设你有
int abc[3] = {1,2,3};
int* ptr = &abc[0];
&ptr[2]
( ptr + 2
) 是 的地址,3
明显比 的地址多 8 个1
。
int* PtrA; // assigned memory address 100
int a = 1; // assigned memory address 600
What is the memory address of ptrA + 2?
这个问题是模棱两可的。
如果问题是“什么是(ptrA 的内存地址)+ 2?”,那么您说ptrA
的是内存地址 100(忽略 PtrA != ptrA),并且将 2 添加到 C 和 C++ 中的指针会增加指向类型大小的倍数,所以如果int
是 32 位,那么最终结果是 100 + 2 * 4 = 108。
如果问题是“(ptrA + 2) 的内存地址是什么?”,这意味着将 ptrA 变量和 2 中的值相加的结果,那么这是未定义的,因为没有显示初始化,ptrA
尝试从未初始化的内存中读取。
您的期望和假设的答案表明预期的代码具有...
ptrA = &a;
...在ptrA + 2
评估之前的某个时候。如果这是真的,那么答案将是600 + 2 * sizeof(int)
,很可能是 608。
在 C/C++ 中,指针算法使用指针指向的对象的大小。前任:
int* PtrA = (int*)600;
PtrA+2
如果整数的大小为 4,则的值为608。
标准允许仅在数组内部或“在数组之后”进行指针运算。这意味着应该采取一定的谨慎措施。
我认为,地址总是更多是不正确的。它也可以更少。可以肯定的是,说 ptr 是指向整数数组 a 的基地址的指针,那么 ptr+2 将指向数组的第三个元素。所以如果数组的基地址是600,那么地址可以是600+2*(sizeofIint)),也可以是600-2*sizeof(int);但无论如何,它将指向该数组的第三个元素。所以,我相信即使在数组的情况下,我们也不应该依赖直接地址。并且不应该对 ptr+2 是否指向 608 或其他内容做出任何假设。
谢谢和问候, Saurabh