2009-01-27 124 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; 
相關問題