86

I want to copy an identical struct into another and later on use it as a comparance to the first one. The thing is that my compiler gives me a warning when Im doing like this! Should I do it in another way or am I doing this wrong:

In header File:

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

In C file:

struct RTCclk RTCclk;
struct RTCclk RTCclkBuffert;

void FunctionDO(void)
{
   ... // Some Code
   /* Copy first struct values into the second one */
   memcpy(&RTCclk, &RTCclkBuffert, sizeof RTCclk);
}
Christian
  • 1,548
  • 2
  • 15
  • 26
  • 6
    What warning does the compiler give? – Nick Shaw Feb 03 '12 at 10:39
  • 1
    PS - shouldn't the sizeof call be `sizeof(RTCclk)`, not `sizeof TRCclk`? – Nick Shaw Feb 03 '12 at 10:40
  • Just an Warning [2054] suspicious pointer conversion, should I mabye use memset or memmove instead? – Christian Feb 03 '12 at 10:43
  • 7
    @NickShaw: the parenthesis are redundant, as in `i = (2)+(4);`. I don't like them; some other people do. – pmg Feb 03 '12 at 10:44
  • i would use sizeof (struct RTClk) – Peter Miehle Feb 03 '12 at 10:49
  • 1
    The only reference I can find to "Warning [2054] suspicious pointer conversion" relates to the Microchip compilers for PICs. Their memory maps can be accessed in different ways, and can be affected by things like banking, so you should double check what the signature of memcpy() is and where your variables have been placed by the linker. Perhaps using structure assignment as has been answered is the safest choice. – tinman Feb 03 '12 at 10:56
  • It goes like thos: size of some_variable, sizeof (TYPE). see here: https://stackoverflow.com/a/26652883/20626793 – Goola Nov 29 '22 at 10:03

7 Answers7

190

For simple structures you can either use memcpy like you do, or just assign from one to the other:

RTCclk = RTCclkBuffert;

The compiler will create code to copy the structure for you.


An important note about the copying: It's a shallow copy, just like with memcpy. That means if you have e.g. a structure containing pointers, it's only the actual pointers that will be copied and not what they point to, so after the copy you will have two pointers pointing to the same memory.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 8
    does it work even if I have arrays inside struct? like: struct example{ int myThings[10000]; char name[100]; int id; }; – M4rk Jan 07 '14 at 16:35
  • 1
    How do I do a deep copy then? – User Mar 27 '15 at 06:17
  • 5
    @User If the structure doesn't contain any pointers, and contained structures doesn't contain pointers, and so on, then that's take care of. If there's pointers anywhere, you need to allocate new memory and copy using e.g. `memcpy`. – Some programmer dude Mar 27 '15 at 06:19
  • Yes, it's a linked list. So just memcpy the first item in the linked list? – User Mar 27 '15 at 06:21
  • 4
    @User If you want to copy a list, the easiest way is to create a list completely from scratch. Loop over the existing list and get its data, then add it to the new list. – Some programmer dude Mar 27 '15 at 06:24
19

Your code is correct. You can also assign one directly to the other (see Joachim Pileborg's answer).

When you later come to compare the two structs, you need to be careful to compare the structs the long way, one member at a time, instead of using memcmp; see How do you compare structs for equality in C?

Community
  • 1
  • 1
Graham Borland
  • 60,055
  • 21
  • 138
  • 179
  • So I should then do something like this: dowhile ( RTCclk.second != RTCclkBuffert.second || RTCclk.minute != RTCclkBuffert.minute || RTCclk.hour != RTCclkBuffert.hour || RTCclk.mday != RTCclkBuffert.mday); – Christian Feb 03 '12 at 12:09
  • 1
    Yes. Although it might be neater to wrap the comparison in a function. – Graham Borland Feb 03 '12 at 12:12
7

copy structure in c you just need to assign the values as follow:

struct RTCclk RTCclk1;
struct RTCclk RTCclkBuffert;

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

RTCclkBuffert=RTCclk1;

now RTCclkBuffert.hour will have value 5,

RTCclkBuffert.minute will have value 4

RTCclkBuffert.second will have value 3

Hemant Metalia
  • 29,730
  • 18
  • 72
  • 91
2

Also a good example.....

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;
}
newrev426
  • 31
  • 3
2

memcpy expects the first two arguments to be void*.

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

P.S. although not necessary, convention dictates the brackets for the sizeof operator. You can get away with a lot in C that leaves code impossible to maintain, so following convention is the mark of a good (employable) C programmer.

Dan
  • 29
  • 1
1

Your memcpy code is correct.

My guess is you are lacking an include of string.h. So the compiler assumes a wrong prototype of memcpy and thus the warning.

Anyway, you should just assign the structs for the sake of simplicity (as Joachim Pileborg pointed out).

undur_gongor
  • 15,657
  • 5
  • 63
  • 75
  • 3
    `memcpy` for structures says "I don't know that the language I'm using supports structure assignment". The only reason to ever use memcpy between two structs of identical type is that for some reason you need to ensure that the struct padding is preserved exactly. – Kaz Feb 13 '16 at 19:42
0

I think you should cast the pointers to (void *) to get rid of the warnings.

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

Also you have use sizeof without brackets, you can use this with variables but if RTCclk was defined as an array, sizeof of will return full size of the array. If you use use sizeof with type you should use with brackets.

sizeof(struct RTCclk)
Alpha
  • 21
  • 1
  • 3