10

我试图将包含整数、字符和字符数组的结构的成员复制到字节数组中以发送到串行线路。到目前为止我有

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

戴夫

4

7 回答 7

9

您不必实际将结构复制到字节数组中。您可以选择这样做:

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

指针的威力!:)

于 2009-01-27T18:13:39.117 回答
9

抱歉,直到现在我才看到你的评论。下面的代码在 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;
}

我希望这有帮助。

~~
_

于 2009-01-28T22:50:03.037 回答
1

这相当简单: 1. ArrayBuild 接受一个指向 msg_on_send 结构的指针,并且对于其中的每个成员,使用 memcpy 将字节复制到传入的 char 数组中,如下所示 -

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 只给出了一个字符数组和一个大小 - 它依次抓取每个字符并使用 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() 调用将被对串行端口写入的调用所取代。

于 2009-01-27T17:50:26.747 回答
1

如果我想将结构视为字节数组,我通常使用联合将结构与字节数组组合。例如:

typedef union
{
    struct
    { 
        char descriptor_msg[5]; 
        int  address; 
        char space; 
        char cmdmsg[5]; 
        char CR; 
        char LF; 
    };
    BYTE bytes[];
} msg_on_send;
于 2010-02-08T18:56:07.820 回答
1

完整的示例。完美的作品。在 X-CODE 9 Objective-C 下测试

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Person
{
    char name[20];
    int age;
};

int main()
{
    //structure variable declaratio with initialisation
    struct Person person={"Deniss Ritchie", 60};
    //declare character buffer (byte array)
    unsigned char *buffer=(char*)malloc(sizeof(person));
    int i;

    //copying....
    memcpy(buffer,(const unsigned char*)&person,sizeof(person));

    //printing..
    printf("Copied byte array is:\n");
    for(i=0;i<sizeof(person);i++)
        printf("%02X ",buffer[i]);
    printf("\n");

    //freeing memory..
    free(buffer);
    return 0;
}

输出:

Copied byte array is:
44 65 6E 69 73 73 20 52 69 74 63 68 69 65 00 00 00 00 00 00 3C 00 00 00
于 2018-03-27T11:18:20.123 回答
0

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

成员到成员的复制最有可能执行以应对对齐,因为(char*) &address可能大于((char*) &descriptor_msg) + 5.

USARTWriteHEX结构字节的代码发送到stdout,但放弃对齐。使用不同的对齐策略编译此代码将导致不同的输出。

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

于 2009-01-27T17:44:48.740 回答
0

一个很好的解决方案:

typedef union
{
  unsigned char byte_array[14];
  struct
  {
    uint8_t descriptor_msg[5];
    uint8_t address;
    uint8_t space;
    uint8_t cmdmsg[5];
    uint8_t CR;
    uint8_t LF;
  };
} msg_to_send_t;

#define ARRAY_OF_5_BYTE {0x00, 0x01, 0x02, 0x03, 0x04}

#define MSG_TO_SEND_DEFAULT \
{ \
   .descriptor_msg = ARRAY_OF_5_BYTE, \
   .address = 0x01, \
   .space = 0x02, \
   .cmdmsg = ARRAY_OF_5_BYTE,\
   .CR = 0x03, \
   .LF = 0x04, \
} 

msg_to_send_t msg = MSG_TO_SEND_DEFAULT;

for(i=0; i<sizeof(msg.byte_array); i++)
    printf("%02x", msg.byte_array[i]);
printf("\r\n");
于 2021-05-14T10:55:30.733 回答