C의 구조물 멤버를 바이트 어레이에 복사하려고
-
20-08-2019 - |
문제
INT, 숯 및 숯의 혼합물을 포함하는 구조물의 부재를 일련 라인으로 보내기 위해 바이트 배열로 복사하려고합니다. 지금까지 나는 가지고있다
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 함수가 이것을 문자열에 어떻게 패키지하는지 또는 배열을로드하는 방법을 모르겠습니다. 내 구조 초기화.
죄송 합니다이 게시물은 조금 길지만이 프로그래밍을 시작 하고이 개념을 중심으로 머리를 잡으려고 노력하고 있습니다.
감사합니다 Dave
편집하다:
와우, 많은 좋은 답변 - 감사합니다.
Slaz : 그것은 나에게 논리적으로 보인다. 나는 아직도 포인터 주위에 머리를 얻지 못했기 때문에 그 접근법에 대해 실제로 생각하지 않았지만 그들이 C의 필수 부분임을 알기 시작했다. 그래서 나는 정식으로 가질 것이다. 외모.
이 코드 라인은 데이터를 내 UART로 보냅니다. 메시지 내용이 포함 된 배열을 무엇으로 바꾸겠습니까? 내 구조가 어디에서 시작되는지, 얼마나 큰지 알려주는 변수가있는 사람들이 여기에 논리적 인 단계를 놓치고있는 것 같습니다.
USART_SendData(USART1, message_on_contents[array_count]);
Harper Shelby : 그 설명에 감사드립니다. 제 생각에는 훨씬 더 명확 해집니다.
RGD
데이브
해결책
죄송합니다. 지금까지 귀하의 의견을 보지 못했습니다. 아래 코드는 Linux에서 잘 컴파일되므로 잘 작동하기를 바랍니다.
printf ()는 16 진수로 인쇄하고 있으며 각 바이트마다 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;
}
이게 도움이 되길 바란다.
~
~
다른 팁
실제로 구조물을 바이트 배열로 복사 할 필요는 없습니다. 선택적으로 다음을 수행 할 수 있습니다.
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));
포인터의 힘! :)
구조를 바이트 배열로 취급하려면 일반적으로 조합을 사용하여 구조를 바이트 어레이와 결합합니다. 예를 들어:
typedef union
{
struct
{
char descriptor_msg[5];
int address;
char space;
char cmdmsg[5];
char CR;
char LF;
};
BYTE bytes[];
} msg_on_send;
당신의 struct
바이트 배열은 다음과 같습니다. 여기에는 포인터가 포함되어 있지 않습니다.
회원 간 사본은 다음과 같이 조정에 대처하기 위해 수행됩니다. (char*) &address
아마도 더 클 것입니다 ((char*) &descriptor_msg) + 5
.
USARTWrite
보낸다 HEX
구조물의 바이트 코드 stdout
, 그러나 정렬을 폐기합니다. 다른 정렬 전략 으로이 코드를 컴파일하면 출력이 다릅니다.
구조 선언을 동봉하십시오 #pragma pack(push, n)
그리고 #pragma pack(pop)
정렬을 강요하고 구조를 바이트-바이트로 복사하십시오.
상당히 간단합니다. 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에는 숯 배열과 크기가 주어집니다. 각 숯을 차례로 잡고 printf ()가있는 16 진수로 화면에 인쇄합니다.
'마법'은 배열 건축에 있습니다. Memcpy는 번역없이 소스에서 대상까지의 바이트 사본을 수행합니다. 4 바이트 INT를 가정하면 함수에 의해 구축 된 배열은 다음과 같습니다.
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 () 호출은 일련의 포트 쓰기에 대한 호출로 대체 될 것이라고 가정합니다.
완전한 완전한 예. 완벽하게 작동합니다. 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