尝试将结构成员复制到c中的字节数组

发布于 2024-07-13 08:13:47 字数 3050 浏览 5 评论 0原文

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

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

Harper Shelby:谢谢您的描述,它使我的头脑更加清晰。

戴夫

I am attempting to copy the members of a struct containing a mixture of ints, char's and arrays of chars into a byte array to send to a serial line. So far I have

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

As I obtained this code, I don't fully understand how it works. I can see that the memcpy takes each element of the struct and makes it into a serial stream indexed by the 'i' variable, but I don't know how the USARTWrite function packetises this into a string, or how to load the array with my struct initialisation.

Sorry this post is a bit long, but I'm just starting this programming lark, and trying to get my head around this concept.

Thanks
Dave

EDIT:

wow, many good answers quickly - thanks guys.

slaz: That seems logical to me, I hadn't really thought about that approach as I haven't really got my head around pointers yet, but I am beginning to see that they are an essential part of C, so I duly will have a look.

  • This line of code sends the data to my UART, what would I replace the array containing the message contents with? It seems like I am missing a logical step here where I have a variable telling me where my structure starts and how big it is, but no array to send

    USART_SendData(USART1, message_on_contents[array_count]);
    

Harper Shelby: Thank you for that description, it makes it much clearer in my mind.

rgds

Dave

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

淡笑忘祈一世凡恋 2024-07-20 08:13:47

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

我希望这有帮助。

~

Sorry, I didn't see your comment until just now.
The code below compiles on Linux just fine, so I hope it works for you.
printf() is printing in hex, you will get 2 characters for each 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;
}

I hope this helps.

~
~

蹲在坟头点根烟 2024-07-20 08:13:47

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

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

指针的力量! :)

You don't have to actually copy the struct into an array of bytes.
You could optionally do this:

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

The power of pointers! :)

遮云壑 2024-07-20 08:13:47

完整的完整示例。 完美运作。 在 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

Full complete example. Perfectly works. Tested under 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;
}

Output:

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
碍人泪离人颜 2024-07-20 08:13:47

这相当简单:
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 只是给出一个 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() 调用将替换为对串行端口写入的调用。

It's fairly straightforward:
1. ArrayBuild takes a pointer to a msg_on_send structure, and for each member in there, uses memcpy to copy the bytes into a char array that was passed in like so -

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 is just given a char array and a size - it grabs each char in turn and prints it to the screen as a hex value with printf().

The 'magic' is in the ArrayBuild - memcpy does a literal copy of bytes from source to destination, with no translation. Assuming 4-byte ints, the array built by the function will look like so:

                     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)

I'd assume that in the 'real' application, the printf() call would be replaced by a call to a serial port write.

没有伤那来痛 2024-07-20 08:13:47

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

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

If I want to treat a structure as an array of bytes I typically use a union to combined the structure with a byte array. For example:

typedef union
{
    struct
    { 
        char descriptor_msg[5]; 
        int  address; 
        char space; 
        char cmdmsg[5]; 
        char CR; 
        char LF; 
    };
    BYTE bytes[];
} msg_on_send;
柠北森屋 2024-07-20 08:13:47

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

成员到成员的复制很可能是为了处理对齐问题,因为 (char*) &address 可能会大于 ((char*) &descriptor_msg) + 5< /代码>。

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

将结构声明包含在 #pragma pack(push, n)#pragma pack(pop) 中以强制对齐,然后只需逐字节复制结构即可。

Your struct here is just array of bytes, it contains no pointers that point out of it.

Member-to-member copy is most likely performed to cope with alignment, as (char*) &address will likely be greater than ((char*) &descriptor_msg) + 5.

USARTWrite sends HEX codes of the bytes of your struct to stdout, but discards alignment. Compiling this code with different alignment strategies will lead to different outputs.

Enclose your structure declaration into #pragma pack(push, n) and #pragma pack(pop) to force alignment, and just copy your structure byte-to-byte.

烟凡古楼 2024-07-20 08:13:47

一个好的解决方案:

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

A good solution:

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");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文