尝试将结构成员复制到c中的字节数组
我试图将包含int、char和char数组的混合结构的成员复制到字节数组中,以发送到串行行。到目前为止我有尝试将结构成员复制到c中的字节数组,c,arrays,serialization,struct,memcpy,C,Arrays,Serialization,Struct,Memcpy,我试图将包含int、char和char数组的混合结构的成员复制到字节数组中,以发送到串行行。到目前为止我有 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_sen
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]);
Dave您的
结构
这里只是一个字节数组,它不包含指向它的指针
成员到成员的复制很可能是为了处理对齐,因为(char*)和address
可能大于((char*)和descriptor_msg)+5
USARTWrite
将结构字节的HEX
代码发送到stdout
,但放弃对齐。使用不同的对齐策略编译此代码将导致不同的输出
将结构声明包含在
#pragma pack(push,n)
和#pragma pack(pop)
中以强制对齐,只需将结构逐字节复制即可。这相当简单:
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)
我假设在“real”应用程序中,printf()调用将替换为对串行端口写入的调用。您不必实际将结构复制到字节数组中。 您可以选择执行以下操作:
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));
指针的力量!:) 对不起,我刚才才看到你的评论。 下面的代码在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;
}
#包括
发送上的结构消息
{
字符描述符_msg[5];
int地址;
字符空间;
char-cmdmsg[5];
炭铬;
字符LF;
};
void USARTWrite(常量void*对象,大小)
{
常量无符号字符*字节;
对于(字节=对象;大小--;++字节)
{
printf(“%02X”,*字节);
}
putchar('\n');
}
int main(int argc,字符**argv)
{
发送myMsg时的struct msg\u;
无符号字符*ptr=(无符号字符*)&myMsg;
USARTWrite(ptr,sizeof(myMsg));
返回0;
}
我希望这有帮助
~~如果我想将一个结构作为一个字节数组来处理,我通常使用一个并集将该结构与一个字节数组组合起来。例如:
typedef union
{
struct
{
char descriptor_msg[5];
int address;
char space;
char cmdmsg[5];
char CR;
char LF;
};
BYTE bytes[];
} msg_on_send;
完整的例子。非常有效。在X代码9目标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;
}
一个好的解决方案:
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");
typedef联合
{
无符号字符字节数组[14];
结构
{
uint8_t描述符_msg[5];
uint8_t地址;
uint8_t空间;
uint8_t cmdmsg[5];
uint8_t CR;
uint8_t LF;
};
}发送消息;
#定义_5_字节{0x00,0x01,0x02,0x03,0x04}的数组_
#默认情况下定义消息发送\
{ \
.descriptor\u msg=数组,共5个字节\
.address=0x01\
.space=0x02\
.cmdmsg=数组,共5个字节\
.CR=0x03\
.LF=0x04\
}
msg_to_send_t msg=msg_to_send_默认值;
对于(i=0;您正在寻找的工作是“序列化”.Re-tagged.不挑剔,但在大西洋的这一边,我们使用“s”而不是“z”。只是英语的语义真的很公平。DaveThe问题没有指定平台或编译器,标记也没有指定。根据定义,Pragmas不是标准的,编译器之间也有差异。建议使用Pragmas时,请至少通过compile来限定r、 这是很常见的,我看到它一直被用来将大窗口api结构归零。但是我不会通过TEPTR生成temp变量。为什么不生成此temp变量?您必须具有属性((打包))为了保证结构始终按预期工作,我很抱歉,但我真的不明白你的意思,你能用一种更简单的方式解释一下吗?我刚刚开始编程。如果你使用这种技术,请确保接收端与发送端具有相同的端号。否则,你会得到奇怪的整数由于USARTWrite采用const void*,因此应该需要在main中使用ptr变量。您可以这样做:USARTWrite(&myMsg,sizeof(myMsg));您能提供更多的解释吗?您的代码与其他答案中没有的有什么不同?
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");