изменение значения указателя после его возвращения из функции - PullRequest
0 голосов
/ 16 мая 2019

Я пытался изменить адрес, на который указывает указатель int после его создания. Хотя это работает поначалу, последовательные вызовы функции, которая изменяет значение указателя, не изменят первоначальное значение, которое я намеревался изменить, и воздействуют только на значения локально в функции. Я полагаю, что указатель может по какой-то причине менять значение между рекурсивными вызовами функций.

Я пытаюсь создать код, который сгенерирует сетевой список соединений. Он рекурсивно обходит двоичное дерево, возвращая пару указателей на указатель при создании узла, причем пара представляет начальные и конечные значения этого узла соответственно. когда пара получается от каждого из 2 дочерних элементов в двоичном дереве, мой код затем объединяет 2 узла, делая указатель, указывающий на конец одного из 2 узлов, равным другому, так что они оба имеют одинаковое значение (указав на один и тот же адрес), и если одно из 2 будет изменено позже, значения 2 будут изменены, поскольку теперь они оба указывают на одно и то же местоположение. затем он возвращает указатель, указывающий на начало первого узла и конец второго узла. Затем эта пара возвращается для использования в качестве дочернего элемента для своего родителя.

Странно то, что при первом объединении 2 пар это корректно меняет значение исходного указателя, но не происходит, когда я вызываю его несколько раз.

Причина, по которой я возвращаю указатель на указатель, заключается в том, что я не могу вернуть ссылку на указатель, поэтому я изменяю исходное значение, поэтому в качестве обходного пути я возвращаю указатель, который указывает на указатель Я хочу измениться.

Проблема возникает при использовании функций create_and и create_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.

...