从函数返回指针后更改指针的值

时间:2019-05-16 00:33:30

标签: c++ pointers recursion reference binary-tree

我一直试图在创建int指针后更改其指向的地址。尽管起初是可行的,但是连续更改指针值的函数调用不会更改我打算更改的原始值,而只会在函数中局部影响值。我认为,由于递归函数调用之间的某种原因,指针可能会更改其值。

我正在尝试创建将生成电路网表的代码。它递归地遍历二叉树,在创建节点时将一对指针返回一个指针,该对分别代表该节点的开始和结束值。当从二叉树的2个子节点中的每个子节点获得一对时,我的代码然后合并2个节点,使指针指向2个节点之一的末端,等于另一个,以便它们都共享相同的值(通过poiting到相同的地址),如果稍后更改2个值之一,则2个值都会更改,因为它们现在都指向相同的位置。然后它返回指向第一个节点的起点和第二个节点的终点的指针。然后,该对将返回以用作其父级的子级。

奇怪的是,第一次2对被合并时,它会正确更改原始指针的值,但是当我多次调用它时并不会更改。

我将指针返回指针的原因是,我无法返回对该指针的引用,因此无法更改原始值,因此,要解决此问题,我将返回指向该指针的指针我想改变。

使用create_andcreate_or函数时会出现问题。

std::pair<int**, int**> create_and(std::pair<int**, int**> &in1, std::pair<int**, int**> &in2) {
    delete *in2.first;
    *in2.first = *in1.second;
    in2.first = in1.second;
    return {in1.first, in2.second};
}

std::pair<int**, int**> create_or(std::pair<int**, int**> &in1, std::pair<int**, int**> &in2) {
    delete *in2.first;
    delete *in2.second;
    *in2.first = *in1.first;
    in2.first = in1.first;
    *in2.second = *in1.second;
    in2.second = in1.second;
    return {in1.first, in1.second};
}

完整代码以及测试用例

#include <iostream>
#include <cstring>
#include <vector>

const int N = 1e3;

char tree[N] = {'&', '|', '|', 'a', 'b', 'c', 'd', 0, 0, 0, 0, 0, 0, 0, 0};


struct mos {
    int* drn;
    int* bdy;
    int* snk;
};

std::vector<mos*> up_netlist, down_netlist;

int* Vdd, *gnd;
int uni1 = 105;
int nMOS = 0, pMOS = 0;
int inter = 1000;
int count = 0;
int inter1 = 1000;
bool up_down;

std::pair<int**, int**> get_ends(int = 0);
std::pair<int**, int**> create_and(std::pair<int**, int**>&, std::pair<int**, int**>&);
std::pair<int**, int**> create_or(std::pair<int**, int**>&, std::pair<int**, int**>&);
std::pair<int*, int*> create_not(std::pair<int*, int*>&);

int main(){


    //memset(tree, -1, sizeof tree);
    Vdd = new int;
    *Vdd = 1;
    gnd = new int;
    *gnd = -1;
    int* y = new int;
    *y = 111;
    up_down = true;
    std::pair<int**, int**> up = get_ends(); //returns a pair of pointers that are the start and end wire for the generated pull up network
    up_down = false;
    std::pair<int**, int**> down = get_ends();
    **up.first = *Vdd; //make start = Vdd
    **up.second = *y; //make end = y
    **down.first = *y;
    **down.second = *gnd;
    std::cout << "Vdd: " << **up.first << std::endl << "Gnd: " << **down.second << std::endl << std::endl << std::endl << "Netlist: " << std::endl << std::endl;
    int j = 0;
    for (auto i : up_netlist) {
        std::cout << 'M' << j++ << ' ' << *i->snk << ' ' << *i->bdy << ' ' << *i->drn << ' ' << *i->drn << ' ' << "PMOS" << std::endl; //printing netlist
    }
    for (auto i : down_netlist) {
        std::cout << 'M' << j++ << ' ' << *i->snk << ' ' << *i->bdy << ' ' << *i->drn << ' ' << *i->drn << ' ' << "NMOS" << std::endl;
    }

    return 0;

}


//To better interpret this, suppose the view from the function opinion is just a tree with a parent and 2 children nodes with each node presenting a circuit (except the parent). The children return the their start and end wires to the parent. The parent then combines the 4 wires together down to 2 according to the parent's value. The parent then returns the 2 new wires.
std::pair<int**, int**> get_ends(int parent_loc) {
    char parent = tree[parent_loc]; //parent to evaluate

    int child_1_loc = parent_loc * 2 + 1, child_2_loc = child_1_loc + 1; //location of parents children

    char child_1 = tree[child_1_loc]; //value of child
    char child_2 = tree[child_2_loc]; //value of child

    std::pair<int**, int**> child_1_end, child_2_end; //will be the start and end wires that will be recursively returned

    if (child_1 != 0) {
        child_1_end = get_ends(child_1_loc); //start and end wires of child 1
    }

    if (child_2 != 0) {
        child_2_end = get_ends(child_2_loc); //start and end wires of child 2
    }

    std::pair<int**, int**> ret;

    if (child_1 != 0 && child_2 != 0) { //enter case if children not null and parent is one of &, | or '. meaning the children have their start and end wires ready
        switch (parent) {
            case '&' : if (up_down) {
                    ret = create_and(child_1_end, child_2_end);
                } else {
                    ret = create_or(child_1_end, child_2_end);
                }
                break;
            case '|': if (up_down) {
                    ret = create_or(child_1_end, child_2_end);
                } else {
                    ret = create_and(child_1_end, child_2_end);
                }
                break;
            case '\'': //ret = create_not(child_1_end);
                break;
            default: std::cout << "ERROR";
        }
    } else { //this creates the start and end wires that are to be combined
        mos* new_mos = new mos;
        new_mos->bdy = new int;
        *new_mos->bdy = parent;
        new_mos->drn = new int;
        *new_mos->drn= ++uni1;
        new_mos->snk = new int;
        *new_mos->snk = ++uni1;
        if (up_down) {
            up_netlist.push_back(new_mos); //push to the netlist so we can output it later and values are still changed in the netlist due to pointers
        } else {
            down_netlist.push_back(new_mos);
        }
        ret = {&new_mos->drn, &new_mos->snk}; //start and end of a single MOSFET
    }
    return ret;
}


std::pair<int**, int**> create_and(std::pair<int**, int**> &in1, std::pair<int**, int**> &in2) {
    delete *in2.first;
    *in2.first = *in1.second;
    in2.first = in1.second;
    return {in1.first, in2.second};
}

std::pair<int**, int**> create_or(std::pair<int**, int**> &in1, std::pair<int**, int**> &in2) {
    delete *in2.first;
    delete *in2.second;
    *in2.first = *in1.first;
    in2.first = in1.first;
    *in2.second = *in1.second;
    in2.second = in1.second;
    return {in1.first, in1.second};
}

std::pair<int*, int*> create_not(std::pair<int*, int*> &in) {
    int* inter = new int;
    *inter = inter1;
    mos* new_mos = new mos;
    new_mos->bdy = in.second;
    new_mos->drn = Vdd;
    new_mos->snk = inter;
    mos* new_mos_2 = new mos;
    new_mos_2->bdy = in.second;
    new_mos_2->drn =  inter;
    new_mos_2->snk = gnd;
    return {in.first, inter};
}

结果是:

M0 107 97 1 1 PMOS
M1 107 98 1 1 PMOS
M2 111 99 107 107 PMOS
M3 111 100 431886464 431886464 PMOS
M4 115 97 111 111 NMOS
M5 -1 98 115 115 NMOS
M6 119 99 111 111 NMOS
M7 -1 100 119 119 NMOS

我要更改的原始指针未正确更新。

应该在什么时候出现:

M0 107 97 1 1 PMOS
M1 107 98 1 1 PMOS
M2 111 99 107 107 PMOS
M3 111 100 107 107 PMOS
M4 115 97 111 111 NMOS
M5 -1 98 115 115 NMOS
M6 119 99 111 111 NMOS
M7 -1 100 119 119 NMOS

错误的值应指向存储107的相同地址。

0 个答案:

没有答案