Копировать содержимое одного указателя в другое

#c #pointers

#c #указатели

Вопрос:

Я думал, что где-то читал, что при использовании указателей и мы хотим скопировать содержимое одного в другое, есть два варианта:

  • используя memcpy или
  • просто назначая им = ?

Однако в приведенном ниже примере я просто протестировал его, выделив память для двух указателей, затем назначив второй, изменив первый … но затем запись моего второго указателя также меняется.. Что я делаю не так:/.

 typedef struct {

    int a;
    int b;
    int c;
} my_struct;


int main(int argc, char** argv) {

    my_struct* first = malloc(sizeof(my_struct));   
    first->a = 100; first->b = 101; first->c = 1000;

    my_struct* bb = malloc(sizeof(my_struct));  

    printf("first %d %d %dn", first->a, first->b, first->c);
    bb = first;
    printf("second %d %d %dn", bb->a, first->b, bb->c);


    first->a = 55; first->b = 55; first->c = 89;
    printf("second %d %d %dn", bb->a, first->b, bb->c);
}
  

Ответ №1:

В тот момент, когда вы это делаете bb = first; , bb и first указываете на одно и то же местоположение памяти. first->a = 55; first->b = 55; first->c = 89; изменит значения для a , b , и c в этом расположении. Исходное значение first , все еще сохраняется в памяти, но к нему больше нет доступа.

Я думаю, что вы можете захотеть сделать это *bb = *first; .

Комментарии:

1. Хорошо, большое спасибо за объяснение, оно сделало его немного более понятным.. Но каково соглашение в C о копировании содержимого, является ли memcpy более распространенным или назначением, которое вы написали?

2. Я не думаю, что существует соглашение как таковое . Это действительно зависит от сценария, поскольку копирование данных, содержащих указатели, является довольно сложной темой, IMO.

3. Итак, у *pointer = *other_pointer меня всегда есть гарантия, что содержимое, стоящее за other_pointer , скопировано в местоположение pointer ?

4. …Исходное значение bb все еще сохраняется в памяти..

Ответ №2:

Ваши знания memcpy верны, но вы не можете назначить содержимое «местоположения, на которое указывают указатели«, просто назначив указатели, как вы сделали в своем заявлении, упомянутом выше.

Вы присваиваете один указатель другому в следующем операторе:

 bb = first;
  

Теперь оба они указывают на одну и ту же ячейку памяти (считайте bb , что это псевдоним first ).

Если вы хотите скопировать данные, вы копируете, используя «данные, на которые указывают указатели» *bb = *first

Комментарии:

1. Хорошо, значит, в этих случаях нет способа обойти использование memcpy?

2. @malajedala *bb = *first;

Ответ №3:

Как уже указывалось, если у вас есть указатель first , который указывает на некоторое местоположение в памяти, и вы выполняете присваивание bb = first , где bb — совместимый тип указателя, тогда bb указывает на тот же адрес, first что и . Это не копирует содержимое памяти, на которую ссылается, first в местоположение, на которое первоначально ссылается bb . Он копирует значение указателя, которое является адресом, в bb .

Если вы определяете массив A , вы не можете выполнить присваивание B = A для копирования содержимого A в B . Вы должны использовать strcpy() или memcpy() или какую-то такую функцию. Но структуры разные. Вы можете назначить содержимое одной структуры совместимой структуре.

В вашем примере bb и first являются указателями на структуры, и когда вы пишете bb = first , теперь оба указателя ссылаются на один и тот же адрес в памяти, и у вас больше нет доступа к памяти, на которую первоначально ссылается bb — так что теперь у вас утечка памяти! Но *bb и *first являются структурами, и когда вы пишете *bb = *first , содержимое структуры *first копируется в структуру *bb . Итак, теперь у вас есть две разные структуры в разных местах памяти, каждая с копиями одних и тех же трех int файлов.

Если ваш my_struct тип содержит указатель на int , то после назначения *bb = *first каждый из них будет содержать копию указателя на одно и то же место в памяти, но данные, на которые ссылаются эти указатели, не будут скопированы. Итак, если структуры содержали указатель на массив, копировался бы только указатель, а не содержимое массива, которое было бы общим для двух структур.

Ответ №4:

вам нужно скопировать данные, на которые указывают такие указатели, как *p1 = *p2 . Но помните, это не сработает, если у вас снова есть указатели внутри копируемых структур.