取消引用双指针,三指针等

时间:2015-10-26 19:15:59

标签: c++ pointers

下面是我为了玩指针而创建的示例程序。

#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;

有人可以帮我解释一下吗?

4 个答案:

答案 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.