Copiar estructura a estructura en C

5 minutos de lectura

avatar de usuario
cristiano

Quiero copiar una estructura idéntica en otra y luego usarla como comparación con la primera. ¡La cosa es que mi compilador me da una advertencia cuando estoy haciendo esto! ¿Debo hacerlo de otra manera o estoy haciendo esto mal?

En el archivo de cabecera:

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

En el archivo 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);
}

  • ¿Qué advertencia da el compilador?

    – Nick Shaw

    3 de febrero de 2012 a las 10:39

  • PD: ¿no debería ser el tamaño de la llamada? sizeof(RTCclk)no sizeof TRCclk?

    – Nick Shaw

    3 de febrero de 2012 a las 10:40


  • solo una advertencia [2054] Conversión de puntero sospechosa, ¿debería usar memset o memmove en su lugar?

    – cristiano

    3 de febrero de 2012 a las 10:43

  • @NickShaw: los paréntesis son redundantes, como en i = (2)+(4);. no me gustan; algunas otras personas lo hacen.

    – pmg

    3 de febrero de 2012 a las 10:44

  • La única referencia que puedo encontrar a “Advertencia [2054] conversión de puntero sospechosa” se relaciona con los compiladores de Microchip para PIC. Se puede acceder a sus mapas de memoria de diferentes maneras y pueden verse afectados por cosas como la banca, por lo que debe verificar dos veces cuál es la firma de memcpy() y dónde han estado sus variables colocado por el enlazador Quizás usar la asignación de estructura como se ha respondido es la opción más segura.

    – hombre de hojalata

    3 de febrero de 2012 a las 10:56

Para estructuras simples puedes usar memcpy como lo haces tú, o simplemente asigna de uno a otro:

RTCclk = RTCclkBuffert;

El compilador creará un código para copiar la estructura por usted.


Una nota importante sobre la copia: es una copia superficial, al igual que con memcpy. Eso significa que si tiene, por ejemplo, una estructura que contiene punteros, solo se copiarán los punteros reales y no a qué apuntan, por lo que después de la copia tendrá dos punteros apuntando a la misma memoria.

  • ¿Funciona incluso si tengo arreglos dentro de la estructura? como: ejemplo de estructura{ int misCosas[10000]; nombre del personaje[100]; identificación interna; };

    – M4rk

    07/01/2014 a las 16:35

  • ¿Cómo hago una copia profunda entonces?

    – Usuario

    27 de marzo de 2015 a las 6:17

  • @User Si la estructura no contiene punteros, y las estructuras contenidas no contienen punteros, y así sucesivamente, entonces se soluciona. Si hay punteros en cualquier lugar, debe asignar nueva memoria y copiar usando, por ejemplo memcpy.

    – Un tipo programador

    27 de marzo de 2015 a las 6:19

  • Sí, es una lista enlazada. Entonces, ¿solo memcpy el primer elemento en la lista vinculada?

    – Usuario

    27 de marzo de 2015 a las 6:21

  • @User Si desea copiar una lista, la forma más fácil es crear una lista completamente desde cero. Recorra la lista existente y obtenga sus datos, luego agréguelos a la nueva lista.

    – Un tipo programador

    27 de marzo de 2015 a las 6:24

avatar de usuario
graham borland

Su código es correcto. También puede asignar uno directamente al otro (ver la respuesta de Joachim Pileborg).

Cuando luego venga a comparar las dos estructuras, debe tener cuidado de comparar las estructuras a lo largo, un miembro a la vez, en lugar de usar memcmp; ver ¿Cómo se comparan las estructuras para la igualdad en C?

  • Entonces debería hacer algo como esto: dowhile ( RTCclk.segundo != RTCclkBuffert.segundo || RTCclk.minuto != RTCclkBuffert.minuto || RTCclk.hora != RTCclkBuffert.hora || RTCclk.mday != RTCclkBuffert.mday) ;

    – cristiano

    3 de febrero de 2012 a las 12:09

  • Si. Aunque sería mejor envolver la comparación en una función.

    –Graham Borland

    3 de febrero de 2012 a las 12:12

copie la estructura en c, solo necesita asignar los valores de la siguiente manera:

struct RTCclk RTCclk1;
struct RTCclk RTCclkBuffert;

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

RTCclkBuffert=RTCclk1;

ahora RTCclkBuffert.hour tendrá valor 5,

RTCclkBuffert.minute tendrá valor 4

RTCclkBuffert.segundo tendrá valor 3

tambien un buen ejemplo…..

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;
}

Tu memcpy el código es correcto.

Supongo que le falta una inclusión de string.h. Entonces el compilador asume un prototipo incorrecto de memcpy y por lo tanto la advertencia.

De todos modos, solo debe asignar las estructuras en aras de la simplicidad (como señaló Joachim Pileborg).

  • memcpy para estructuras dice “No sé si el lenguaje que estoy usando admite la asignación de estructuras”. La única razón para usar memcpy entre dos estructuras del mismo tipo es que, por alguna razón, debe asegurarse de que el relleno de la estructura se conserve exactamente.

    – Kaz

    13 de febrero de 2016 a las 19:42

avatar de usuario
Dan

memcpy espera que los dos primeros argumentos sean nulos*.

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

PS aunque no es necesario, la convención dicta los corchetes para el tamaño del operador. Puede salirse con la suya con muchas cosas en C que hacen que el código sea imposible de mantener, por lo que seguir las convenciones es la marca de un buen programador de C (empleable).

  • memcpy para estructuras dice “No sé si el lenguaje que estoy usando admite la asignación de estructuras”. La única razón para usar memcpy entre dos estructuras del mismo tipo es que, por alguna razón, debe asegurarse de que el relleno de la estructura se conserve exactamente.

    – Kaz

    13 de febrero de 2016 a las 19:42

avatar de usuario
Alfa

Creo que debería lanzar los punteros a (void *) para deshacerse de las advertencias.

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

También puede usar sizeof sin corchetes, puede usar esto con variables, pero si RTCclk se definió como una matriz, sizeof devolverá el tamaño completo de la matriz. Si usa use sizeof con tipo, debe usar con corchetes.

sizeof(struct RTCclk)

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad