Скопировать структуру в структуру в C - PullRequest
57 голосов
/ 03 февраля 2012

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

В заголовке файла:

extern struct RTCclk
{
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t mday;
uint8_t month;
uint8_t year;
}
RTCclk;

В файле C:

struct RTCclk RTCclk;
struct RTCclk RTCclkBuffert;

void FunctionDO(void)
{
   ... // Some Code
   /* Copy first struct values into the second one */
   memcpy(&RTCclk, &RTCclkBuffert, sizeof RTCclk);
}

Ответы [ 7 ]

128 голосов
/ 03 февраля 2012

Для простых структур вы можете использовать memcpy, как и вы, или просто присвоить одно другому:

RTCclk = RTCclkBuffert;

Компилятор создаст код для копирования структуры для вас.


Важное замечание о копировании: это мелкая копия, как и в случае с memcpy.Это означает, что если у вас есть, например, структура, содержащая указатели, то будут скопированы только фактические указатели, а не то, на что они указывают, поэтому после копирования у вас будет два указателя, указывающих на одну и ту же память.

18 голосов
/ 03 февраля 2012

Ваш код правильный. Вы также можете назначить одно непосредственно другому (см. ответ Иоахима Пилеборга ).

Когда вы позже придете к сравнению двух структур, вам нужно быть осторожным, сравнивая структуры длинного пути, по одному элементу за раз, вместо использования memcmp; см. Как вы сравниваете структуры на равенство в C?

2 голосов
/ 03 февраля 2012

копировать структуру в c, вам просто нужно присвоить значения следующим образом:

struct RTCclk RTCclk1;
struct RTCclk RTCclkBuffert;

RTCclk1.second=3;
RTCclk1.minute=4;
RTCclk1.hour=5;

RTCclkBuffert=RTCclk1;

теперь RTCclkBuffert.hour будет иметь значение 5,

RTCclkBuffert.minute будет иметь значение 4

RTCclkBuffert.second будет иметь значение 3

1 голос
/ 12 января 2015

memcpy ожидает, что первые два аргумента будут недействительными *.

Try: memcpy( (void*)&RTCclk, (void*)&RTCclkBuffert, sizeof(RTCclk) );

P.S. хотя это и не обязательно, соглашение определяет квадратные скобки для оператора sizeof. Вы можете избежать неприятностей в C, что делает код невозможным для поддержки, поэтому соблюдение соглашения является отличительной чертой хорошего (пригодного для использования) программиста на C.

1 голос
/ 03 октября 2013

Также хороший пример .....

struct point{int x,y;};
typedef struct point point_t;
typedef struct
{
    struct point ne,se,sw,nw;
}rect_t;
rect_t temp;


int main()
{
//rotate
    RotateRect(&temp);
    return 0;
}

void RotateRect(rect_t *givenRect)
{
    point_t temp_point;
    /*Copy struct data from struct to struct within a struct*/
    temp_point = givenRect->sw;
    givenRect->sw = givenRect->se;
    givenRect->se = givenRect->ne;
    givenRect->ne = givenRect->nw;
    givenRect->nw = temp_point;
}
1 голос
/ 03 февраля 2012

Ваш memcpy код правильный.

Полагаю, вам не хватает включения string.h. Таким образом, компилятор принимает неправильный прототип memcpy и, следовательно, предупреждение.

В любом случае, вы должны просто назначить структуры ради простоты (как указал Иоахим Пилеборг).

0 голосов
/ 19 января 2016

Я думаю, вы должны привести указатели к (void *), чтобы избавиться от предупреждений.

memcpy((void *)&RTCclk, (void *)&RTCclkBuffert, sizeof RTCclk);

Также вы можете использовать sizeof без скобок, вы можете использовать это с переменными, но если был определен RTCclkв виде массива sizeof возвращает полный размер массива.Если вы используете sizeof с типом, вы должны использовать скобки.

sizeof(struct RTCclk)
...