2009-01-27 11 views
5

Estoy intentando copiar los miembros de una estructura que contiene una mezcla de ints, char's y matrices de caracteres en una matriz de bytes para enviar a una línea serie. Hasta ahora tengotratando de copiar miembros de la estructura a la matriz de bytes en c

struct msg_on_send 
{ 
    char descriptor_msg[5]; 
    int address; 
    char space; 
    char cmdmsg[5]; 
    char CR; 
    char LF; 
}; 

void switch_output_on() 
{ 
    int member; 
    struct msg_on_send SendMsg_on[sizeof member] = 
    { 

    }; 
    unsigned char buffer [ sizeof SendMsg_on[0] ]; 
    showbytes(buffer, serialize(buffer, SendMsg_on)); 
} 

/*************************************************************************** 
* Function: ArrayBuild             * 
* Purpose: Uses memcopy to transfer the struct members sequentially * 
*    into an array of char          * 
* Arguments:                * 
* Returns: size_t i = a count of the number of bytes in the array  * 
***************************************************************************/  

size_t ArrayBuild(unsigned char *dst, const struct msg_on_send *object) 
{ 
    size_t i = 0; 

    memcpy(&dst[i], &object->descriptor_msg, sizeof object->descriptor_msg); 
    i += sizeof object->descriptor_msg; 

    memcpy(&dst[i], &object->address, sizeof object->address); 
    i += sizeof object->address; 

    memcpy(&dst[i], &object->space, sizeof object->space); 
    i += sizeof object->space; 

    memcpy(&dst[i], &object->cmdmsg, sizeof object->cmdmsg); 
    i += sizeof object->cmdmsg; 

    memcpy(&dst[i], &object->CR, sizeof object->CR); 
    i += sizeof object->CR; 

    memcpy(&dst[i], &object->LF, sizeof object->LF); 
    i += sizeof object->LF; 

    return i; 
} 

/*********************************************************************** 
* Function: USARTWrite            * 
* Purpose: Writes the array data to the USART data register  * 
* Arguments: void *object = struct member       * 
*    size_t size = size of array remaining     * 
* Returns: None             * 
***********************************************************************/ 

void USARTWrite(const void *object, size_t size)   
{ 
    const unsigned char *byte; 
    for (byte = object; size--; ++byte) 
    { 
     printf("%02X", *byte); 
    } 
    putchar('\n'); 
} 

Al obtener este código, no entiendo completamente cómo funciona. Puedo ver que la memcpy toma cada elemento de la estructura y la convierte en una secuencia serial indexada por la variable 'i', pero no sé cómo la función USARTWrite empaqueta esto en una cadena, o cómo cargar la matriz con mi inicialización de estructura

Lo siento, esta publicación es un poco larga, pero estoy empezando esta alondra de programación y tratando de entender este concepto.

Gracias a Dave

EDIT:

wow, muchas buenas respuestas rápidamente - gracias chicos.

slaz: Eso me parece lógico, realmente no había pensado en ese enfoque, ya que todavía no he entendido bien los punteros, pero estoy empezando a ver que son una parte esencial de C, por lo que Yo lo veré debidamente.

  • Esta línea de código envía los datos a mi UART, ¿con qué reemplazaría la matriz que contiene el contenido del mensaje? Parece que me estoy perdiendo un paso lógico aquí donde tengo una variable que me dice que mis estructura inicia y lo grande que es, pero no hay variedad para enviar

    USART_SendData(USART1, message_on_contents[array_count]); 
    

Harper Shelby: Gracias por esa descripción , lo hace mucho más claro en mi mente.

rgds

de Dave

+0

El trabajo que está buscando es la "serialización". Re-etiquetado. – dmckee

+0

no siendo quisquilloso, pero en este lado del atlántico usamos una 's' en vez de una 'z. Solo semántica del inglés realmente, bastante justo. Dave – droseman

Respuesta

6

Disculpa, no he visto tu comentario hasta ahora. El siguiente código compila Linux muy bien, así que espero que funcione para usted.
printf() está imprimiendo en hexadecimal, obtendrá 2 caracteres para cada byte.

#include <stdio.h> 

struct msg_on_send 
{ 
char descriptor_msg[5]; 
int address; 
char space; 
char cmdmsg[5]; 
char CR; 
char LF; 
}; 

void USARTWrite(const void *object, size_t size)  
{ 
    const unsigned char *byte; 
     for (byte = object; size--; ++byte)          
     { 
      printf("%02X", *byte); 
     } 
     putchar('\n'); 
} 

int main (int argc, char**argv) 
{ 
    struct msg_on_send myMsg; 
    unsigned char* ptr= (unsigned char*)&myMsg; 

    USARTWrite(ptr, sizeof(myMsg)); 

    return 0; 
} 

Espero que esto ayude.

~ ~

+1

dado que USARTWrite toma un const void *, debería haber una necesidad para la variable ptr en main. Simplemente puede hacer: USARTWrite (& myMsg, sizeof (myMsg)); –

0

Su struct aquí es simplemente array de bytes, que no contiene punteros que apuntan fuera de él.

Es muy probable que se realice una copia de miembro a miembro para hacer frente a la alineación, ya que (char*) &address es probable que sea mayor que .

USARTWrite envía HEX códigos de los bytes de su estructura a stdout, pero descarta la alineación. Compilar este código con diferentes estrategias de alineación conducirá a diferentes resultados.

Adjunte su declaración de estructura en #pragma pack(push, n) y #pragma pack(pop) para forzar la alineación, y simplemente copie su estructura byte a byte.

+0

La pregunta no especifica plataforma o compilador, y tampoco las etiquetas. Los pragmas no son estándar, por definición, y varían entre compiladores. Cuando sugiera pragmas, por lo menos califique por compilador. –

0

Es bastante sencillo: 1. ArrayBuild toma un puntero a una estructura msg_on_send, y para cada miembro de allí, utiliza memcpy para copiar los bytes en una matriz de caracteres que se aprobó en como tal -

char byteArray[17]; // This assumes 4-byte ints 
        // be careful though, the length *must* be long enough, or 
        // Bad Things will happen 
size_t msgSize; // Holds the size of the message built by ArrayBuild, 
       // passed to USARTWrite 
struct msg_on_send myMessage; 
// Code to fill up myMessage appropriately 

msgSize = ArrayBuild(byteArray, &myMessage); // need the & to pass a pointer as required 

USARTWrite(myMessage, msgSize); 

USARTWrite solo tiene una matriz de caracteres y un tamaño: toma cada carácter por vez y lo imprime en la pantalla como un valor hexadecimal con printf().

La 'magia' está en ArrayBuild - memcpy hace una copia literal de los bytes desde el origen hasta el destino, sin traducción. Suponiendo enteros de 4 bytes, la matriz generada por la función se verá así:

     1 1 1 1 1 1 1 
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 
| A  | B |C| D |E|F| 

A = descriptor_msg (char[5]) 
B = address (int) 
C = space (char) 
D = cmdmsg (char[5]) 
E = CR (char) 
F = LF (char) 

Me asumir que en la aplicación 'real', la llamada printf() sería sustituida por una llamada a una serie puerto de escritura.

5

No tiene que copiar realmente la estructura en una matriz de bytes. Usted podría hacer esto opcionalmente:

struct msg_on_send myMessage; 

// code to set myMessage to whatever values... 

// get a byte pointer that points to the beginning of the struct  
uint8_t *bytePtr = (uint8_t*)&myMessage; 

// pass that into the write function, and it will write the amount of bytes passed in 
USARTWrite(bytePtr, sizeof(myMessage)); 

La potencia de los punteros! :)

+0

Esto es bastante común y veo que se usa todo el tiempo para poner a cero las estructuras de la ventana grande. Sin embargo, no haría la variable variable bytePtr. – gradbot

+0

¿por qué no hacer esta variable temporal? – droseman

+0

¡** debe ** tener __atributo__ ((empaquetado)) para la estructura para garantizar que siempre funcionará como se espera! –

1

Si quiero tratar una estructura como una matriz de bytes Me suelen utilizar una unión a la estructura combinada con una matriz de bytes. Por ejemplo:

Cuestiones relacionadas