Правильный способ, чтобы два указателя указывали на один и тот же фрагмент памяти

У меня есть структура:

struct generic_attribute{
    int current_value;
    int previous_value;
};

И конструктор, который выводит указатель на эту структуру:

struct generic_attribute* construct_generic_attribute(int current_value){
    struct generic_attribute *ga_ptr;
    ga_ptr = malloc (sizeof (struct generic_attribute));
    ga_ptr->current_value = current_value;
    ga_ptr->previous_value = 0;
    return ga_ptr;
}

Теперь в другой функции я хочу определить указатель и настроить его так, чтобы он указывал на тот же адрес, что и указатель, который выводит указанный выше конструктор.

struct tagged_attribute* construct_tagged_attribute(int num_args, int *args){
    ...
    struct generic_attribute* generic = malloc (sizeof(struct generic_attribute));
    generic = construct_generic_attribute(args[0]);
    ...
}

Мне кажется, что я здесь делаю следующее:

1) Я определяю указатель как "универсальный" и выделяю блок памяти для хранения экземпляра структуры generic_attribute.

2) Я вызываю функциюstruct_generic_attribute, внутри которой программа снова выделяет кусок памяти размером со структуру generic_attribute. Он выводит указатель на этот фрагмент памяти.

3) Вstruct_tagged_attribute я установил "общий" указатель, равный указателю, выводимому функцией build_generic_attribute, так что теперь они оба указывают на один и тот же слот памяти.

Однако, похоже, я выделяю в два раза больше памяти, чем мне нужно выделить.

Есть ли способ выделить память только один раз, не получая ошибки сегментации из-за того, что не удалось выделить место для «общего» указателя? Или я неправильно понимаю, что происходит в этом коде?


person RebeccaK375    schedule 28.06.2015    source источник


Ответы (3)


struct generic_attribute* generic = construct_generic_attribute(args[0]);

Должен сделать трюк. Переменная-указатель — это просто переменная. Вы можете обменивать значения указателей так же, как числа.

person Will Hartung    schedule 28.06.2015

  1. Да, вы неправильно понимаете, но я не могу понять, что, по вашему мнению, происходит, чтобы объяснить, почему это неправильно.

  2. struct generic_attribute *generic = construct_generic_attribute(args[0]); указатель является своего рода значением. Если вы присваиваете указатель другому, вы получаете два указателя на одно и то же без выделения памяти. Поскольку C не управляет памятью за вас, вы должны убедиться, что любой выделенный объект освобождается ровно один раз, и что вы не пытаетесь использовать указатели на объект после того, как он был освобожден.

person hobbs    schedule 28.06.2015

Здесь

    struct generic_attribute* generic = malloc (sizeof(struct generic_attribute));

вы выделяете блок памяти, достаточно большой для хранения структуры generic_attribute, затем сохраняете указатель на эту структуру (технически: адрес блока) в переменной generic. Примечание. вы не инициализируете элементы структуры.

Затем в

    generic = construct_generic_attribute(args[0]);

вы вызываете функцию, которая внутренне выделяет (другой) блок памяти, инициализирует его и возвращает указатель на него (который был сохранен в переменной ga_ptr во время выполнения функции). Возвращенный указатель затем присваивается переменной generic, перезаписывая значение, сохраненное там предыдущей инструкцией. Следовательно, вы теряете доступ к первой выделенной структуре.

ИЗМЕНИТЬ

Боюсь, я не совсем понимаю, чего вы пытаетесь добиться. Если вам нужны два указателя на одну и ту же структуру, просто объявитеga1 и назначьте ему указатель на созданную структуру:

    struct generic_attribute *ga1 = construct_generic_attribute(args[0]);

затем сделайте копию указателя:

    struct generic_attribute *ga2 = ga1;
person CiaPan    schedule 28.06.2015