2009-01-27 70 views
5

我试图将包含ints,char和chars数组混合的结构的成员复制到字节数组中发送到串行线。到目前为止,我有试图将struct成员复制到字节数组中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'); 
} 

正如我获得此代码,我不完全了解它是如何工作的。我可以看到memcpy获取结构的每个元素,并将其变成由'i'变量索引的串行流,但我不知道USARTWrite函数如何将它分组为字符串,或者如何将该数组加载我的结构初始化。

对不起,这篇文章有点长,但我刚开始编程百灵,试图让我的头脑围绕这个概念。

感谢 戴夫

编辑:

哇,多好的答案很快 - 谢谢你们。 slaz:对我来说这似乎合乎逻辑,我并没有真正想过这种方法,因为我还没有真正掌握指针,但是我开始看到它们是C的一个重要组成部分,所以我应该看看。

  • 这行代码发送数据到我的UART,我会用什么替换包含消息内容的数组?好像我在这里缺少一个合乎逻辑的步骤,我有一个变量,告诉我在哪里,我的结构开始和它多大,但没有数组发送

    USART_SendData(USART1, message_on_contents[array_count]); 
    

哈珀谢尔比:谢谢你的描述,这让我更清楚。

RGDS

戴夫

+0

您正在寻找的工作是“序列化”。重新加标签。 – dmckee 2009-01-27 18:03:53

+0

不挑剔,但大西洋这边我们用's'而不是'z'。只是英语的语义真的很公平。 Dave – droseman 2009-01-28 09:14:30

回答

6

对不起,我直到现在才看到您的评论。 下面的代码在Linux上编译就好了,所以我希望它适合你。
printf()以十六进制打印,每个字节将得到2个字符。

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

我希望这有助于。


0

struct这里是一个字节数组只是,它不包含指针指向了它。

成员对成员副本最有可能执行以应付对齐,因为(char*) &address可能会大于((char*) &descriptor_msg) + 5

USARTWrite发送HEX结构字节代码为stdout,但丢弃对齐。用不同的对齐策略编译此代码将导致不同的输出。

将您的结构声明放入#pragma pack(push, n)#pragma pack(pop)以强制对齐,并且只是复制您的结构字节到字节。

+0

该问题没有指定平台或编译器,也没有标记。根据定义,Pragma不是标准的,编译器之间会有所不同。当提示编译指示时,请至少通过编译器进行限定。 – 2009-01-27 18:15:41

0

这是相当简单: 1. ArrayBuild需要一个指针到msg_on_send结构,以及用于在那里的每个成员,采用的memcpy到字节复制到已传递在像这样一个字符数组 -

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只是给出了一个char数组和一个大小 - 它依次抓取每个char,并使用printf()以十六进制值的形式将其打印到屏幕上。

'魔术'在ArrayBuild中 - memcpy执行从源到目的地的字节拷贝,没有翻译。假设4个字节的整数,由功能内置阵列看起来像这样:

     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) 

我认为在“真正的”应用程序中,printf()的调用将被调用时,一个串行端口写入。

5

您不必将结构实际复制到字节数组中。 你可以任意做:

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

指针的力量! :)

+0

这是很常见的,我看到它一直用来将大窗口API结构清零。我不会让temp变量bytePtr。 – gradbot 2009-01-27 18:52:10

1

如果欲治疗的结构我通常使用并集以组合结构用一个字节数组字节数组。例如:

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