下面是我为了玩指针而创建的示例程序。
#include <iostream>
using namespace std;
void addOne(int** ptr);
void addTwo(int*** ptr);
void addThree(int**** ptr);
void addFour(int***** ptr);
int main()
{
int* ptr = nullptr;
int x = 1;
ptr = &x;
cout << "Original value of x: " << *ptr << endl;
addOne(&ptr);
cin.get();
return 0;
}
void addOne(int** ptr)
{
**ptr += 1;
cout << "After adding 1: " << **ptr << endl;
addTwo(&ptr);
}
void addTwo(int*** ptr)
{
***ptr += 2;
cout << "After adding 2: " << ***ptr << endl;
addThree(&ptr);
}
void addThree(int**** ptr)
{
****ptr += 3;
cout << "After adding 3: " << ****ptr << endl;
addFour(&ptr);
}
void addFour(int***** ptr)
{
*****ptr += 4;
cout << "After adding 4: " << *****ptr << endl;
}
上面的程序会给我以下输出:
Original value of x: 1
After adding 1: 2
After adding 2: 4
After adding 3: 7
After adding 4: 11
现在关注addFour函数:
void addFour(int***** ptr)
{
*****ptr += 4;
cout << "After adding 4: " << *****ptr << endl;
}
我现在所做的是通过这样做减少了addFour函数中*的数量:
void addFour(int***** ptr)
{
****ptr += 4;
cout << "After adding 4: " << ****ptr << endl;
}
当我执行上面的代码时,它给了我以下输出:
Original value of x: 1
After adding 1: 2
After adding 2: 4
After adding 3: 7
After adding 4: 010EFDE0
我的问题是,自从减少* s的数量后,以下语句是做什么的:
****ptr += 4;
cout << "After adding 4: " << ****ptr << endl;
有人可以帮我解释一下吗?
答案 0 :(得分:3)
您将addFour
中的解除引用减少到了四个级别,但该功能仍然需要int*****
。
您的大多数代码都无关紧要,可以简化为:
int x = 1;
cout << "Original value of x: " << *&x << endl;
x += 1;
cout << "After adding 1: " << **&&x << endl;
x += 2;
cout << "After adding 2: " << ***&&&x << endl;
x += 3;
cout << "After adding 3: " << ****&&&&x << endl;
x += 4;
cout << "After adding 4: " << *****&&&&&x << endl;
到目前为止,您的取消引用和操作地址已取消。但是你要问这是什么:
cout << "After adding 4: " << ****&&&&&x << endl;
很简单,您尚未执行最终的取消引用,因此您只需&x
,而不是x
。
&x
是一个指针。在上面的示例中,您将看到内存中x
的地址,以十六进制表示法给出。在您的情况下,您的ptr
具有未指定的值,因为指针算法超出对象的范围具有未定义的行为,但实际上您打印的地址值为x
加{{ 1}}。
答案 1 :(得分:1)
addOne
会收到指向ptr
的{{1}}地址,并将其存储到本地变量x
中。
ptr
收到addTwo
的地址,并将其存储在本地addOne::ptr
变量中。
ptr
收到addThree
的地址,并将其存储在本地addTwo::ptr
变量中。
ptr
收到addFour
的地址,并将其存储在本地addThree::ptr
变量中。因此在ptr
(第二版):
addFour
是*ptr
,addThree::ptr
是**ptr
,addTwo::ptr
是***ptr
和addOne::ptr
是****ptr
。然后将指针增加到4,从而从main::ptr
的地址开始计算第四个int的地址,然后打印该地址。
当然,在第一个版本中x
是*****ptr
,然后您将int main::x
增加4。
答案 2 :(得分:1)
尝试以图形方式可视化,您有:
P -> P -> P -> P -> P -> X
X
是值,P
是指针
每次你写&
时,你都会向左移动,每次你写*
时,你都会向右移动。
因此,如果您有&&&&&x
,并且增加了****x
,则执行以下操作:
P -> P -> P -> P -> P -> X
\
> ?
您向右移动了四个级别,并将指针递增到那里,现在指向X之后的内存位置。
然后你打印****x
,这是一个指针,因为你向右移动了四个级别。
答案 3 :(得分:-1)
// if you want to understand pointers this is my fave example
struct block
{
int data;
struct block *next_block;
};
struct block *block_head = NULL;
add_block(int n) /* add n in the sorted position */
{
struct block *new, *prev = NULL, *bp = block_head;
new = malloc(sizeof(struct block));
new->data = n;
while(bp != NULL)
if(bp->data > n)
{
prev = bp;
bp = bp->next_block;
}
else
{
if(prev == NULL)
{
new->next_block = bp;
block_head = new;
}
else
{
new->next_block = bp;
prev->next_block = new;
}
if(block_head == NULL)
block_head = new;
else
{
prev->next_block = new;
new->next_block = NULL;
}
}
// the above is how you usually do a linked list but it's messy and ugly
// not elegant
// the elegant way to do this is with a double pointer
add_block(int n) /* add n in the sorted position */
{
struct block *new, **bp = &block_head;
new = malloc(sizeof(struct block));
new->data = n;
while(*bp != NULL)
if((*bp)->data > n)
bp = &((*bp)->next_block);
else
break;
new->next_block = *bp;
*bp = new;
}
// if you can understand the elegant version, you probably got pointers down cold.