解引用双指针、三重指针等等

Dereferencing double pointer, triple pointers, and so on

本文关键字:指针 三重 引用      更新时间:2023-10-16

下面是我创建的一个示例程序,用于处理指针。

#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函数中*s的数量,通过这样做:

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;
有人能给我解释一下吗?

您将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加上sizeof(int)的地址的值。

addOne接收到ptr指向x的地址,并将其存储到一个局部变量ptr中。

addTwo接收addOne::ptr的地址,并将其存储在ptr的本地变量中。

addThree接收addTwo::ptr的地址,并将其存储在ptr的本地变量中。

addFour接收addThree::ptr的地址,并将其存储在ptr本地变量中。因此在addFour(第二版本)中:

  • *ptraddThree::ptr
  • **ptraddTwo::ptr
  • ***ptraddOne::ptr
  • ****ptrmain::ptr .

然后将指向int的指针加4,从而从x的地址开始计算第四个int的地址,然后打印该地址。

当然,在第一个版本中,*****ptrmain::x,然后将int x加4

尝试将其可视化,您可以:

P -> P -> P -> P -> P -> X

X为值,P为指针。
每写一次&,就向左移动一次,每写一次*,就向右移动一次。

如果你有&&&&&x,你增加****x,你这样做:

P -> P -> P -> P -> P -> X
                      
                       > ?

您向右移动了四层,并在那里增加了指针,现在指向x之后的内存位置。

然后打印****x,这是一个指针,因为你向右移动了四层

        // 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.