2012-02-03 3 views
47

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

В заголовочном файле:

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); 
} 
+6

Какое предупреждение дает компилятор? –

+0

Предупреждение. ОК. Но, КОТОРЫЙ ОДИН? –

+1

PS - не должен ли sizeof call быть 'sizeof (RTCclk)', а не 'sizeof TRCclk'? –

ответ

112

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

RTCclk = RTCclkBuffert; 

Компилятор будет создавать e, чтобы скопировать структуру для вас.


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

+1

это работает, даже если у меня есть массивы внутри структуры? например: struct example { int myThings [10000]; имя персонажа [100]; int id; }; – rodi

+0

Как мне сделать глубокую копию? – User

+3

@User Если структура не содержит указателей, а содержащиеся в ней структуры не содержат указателей и т. Д., То это позаботится. Если есть указатели в любом месте, вам нужно выделить новую память и скопировать, например, 'Memcpy'. –

2

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

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

16

Ваш код верен. Вы также можете назначить его непосредственно другому (см. Joachim Pileborg's answer).

Когда вы позже пришли, чтобы сравнить две структуры, вам нужно быть осторожным, чтобы сравнить структуры длинным образом, по одному члену за раз, вместо использования memcmp; см. How do you compare structs for equality in C?

+0

Так что я должен затем сделать что-то вроде этого:!! dowhile ( RTCclk.second = RTCclkBuffert.second || RTCclk.minute = RTCclkBuffert.minute || RTCclk.hour = RTCclkBuffert.hour || RTCclk .mday! = RTCclkBuffert.mday); – Christian

+1

Да. Хотя можно было бы опередить сравнение в функции. –

1

Ваш код memcpy верен.

Мое предположение: вам не хватает include string.h. Поэтому компилятор предполагает неправильный прототип memcpy и, таким образом, предупреждение.

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

+0

Это было хорошее предположение, но sting.h был добавлен acctaully:/ – Christian

+2

'memcpy' для структур говорит:« Я не знаю, что язык, который я использую, поддерживает назначение структуры ». Единственная причина когда-либо использовать memcpy между двумя структурами идентичного типа, заключается в том, что по какой-то причине вам нужно убедиться, что заполнение структуры точно сохраняется. – Kaz

0

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

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

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

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

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

0

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

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

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

sizeof(struct RTCclk) 
Смежные вопросы