从指针数组中的地址索引

Index from address in array of pointers?

本文关键字:地址 索引 指针 数组      更新时间:2023-10-16

下面的代码是满足以下要求的解决方案:

"更改 §27.9 中LinkList的表示形式,而不更改函数提供的用户界面。在Links数组中分配Link,并让成员:firstlastprevnext int s(数组中的索引(。"
- 练习 6 第 27 章 - 编程:使用 C++ B. Stroustrup 的原则和实践

该接口继承自侵入式双向链表的普通实现。我添加了 bool 数组(和相关函数(来跟踪内存:

 #include <iostream>
struct Link
{
    int next;
    int prev;
};
//------------------------------------------------------------------------------------
struct List
{
    Link** head;
    int first;      // points to the current first node
    int last;
    bool* available;
    int list_size;
    int get_index()
    {
        for (int i = 0; i < list_size; ++i)
        {
            if (available[i] == true) 
            {
                available[i] = false;
                return i;
            }
        }
        throw std::bad_alloc("bla bla!n");
    }
    List()
    {
        list_size = 30;
        head = new Link*[list_size];
        available = new bool[list_size];
        first = -1;
        last = -1;
        for (int i = 0; i < list_size; ++i)
        {
            available[i] = true;
        }
    }
    void List::push_back(Link* l)
    {
        if (l == nullptr)
        {
            throw std::invalid_argument("bla bla!n");
        }
        int index = get_index();
        head[index] = l;
        if (last != -1)
        {
            head[last]->next = index;
            head[index]->prev = last;
        }
        else
        {
           first = index;
           head[index]->prev = -1;
        }
        last = index;
        head[index]->next = -1;
    }
    void push_front(Link* l)
    {
        if (l == nullptr)
        {
            throw std::invalid_argument("bla blan");
        }
        int index = get_index();
        head[index] = l;
        if (first != -1)
        {
            head[first]->prev = index;
            head[index]->next = first;
        }
        else
        {
            last = index;
            head[index]->next = -1;
        }
        first = index;
        head[index]->prev = -1;
    }
    // index = ptr - base
    std::ptrdiff_t index_from_address(Link* l) { return l - head[0]; }
    Link* front() const { return head[first]; }
};
//------------------------------------------------------------------------------------
int main()
{
    List l;
    for (int i = 0; i < 10; ++i)
    {
        l.push_back(new Link());
    }
    for (int i = 0; i < 10; ++i)
    {
        l.push_front(new Link());
    }
    std::cout <<"first = "<< l.first <<", index = " << l.index_from_address(l.front());
    getchar();
}

预期成果:

first = 19, index = 19

实际结果:

first = 19, index = 194

为什么?

l - head[0]

在这里,您可以比较两个指针的值。您允许数组中的所有指针默认初始化,因此它们的值是不确定的,因此访问值的行为是不确定的。

您可能打算index_from_address查找存储特定指针对象的索引 - 而不是指向的对象,因为指向的对象不在 head 指向的数组中。为此,您必须添加一大堆&

 Link*& front() const // return a reference to the pointer object, not a copy
 //  take a reference to the pointer as an argument, add const for good measure
 std::ptrdiff_t index_from_address(Link*& l) const
// compare the addresses of the pointers, rather than values
 { return &l - &head[0]; }