我正在尝试从C编程的PIC中接收二进制记录。
发送的数据结构如下:
typedef struct{int32 num1;
float num2,num3,num4,num5;
...
}RecordStructure;
typedef union{RecordStructure Record; char Array[48];} My_Rec_Structure;
我的问题是:
前4个字节/字符是否属于int32 num1
,下一个4到float num2
依此类推?
如果是这样,我在传输方面遇到了重大问题;如果没有,我如何识别数据的最终位置?
答案 0 :(得分:3)
第一部分是的,但有一点需要注意。
C标准要求第一个结构成员放置在结构的开头。所以int32将是传输的前四个字节。但是,PIC可能有不同的字节顺序,因此您可能最终从PIC发送0x12345678,并在接收端读取值0x78563412。
至于其余结构成员的地址,您的编译器可以在每个成员之间自由添加填充。通常,这是为了优化内存访问而完成的。
如果您有可能从PIC获得一些文本输出,则可以使用stddef.h中的offsetof()宏来获取结构成员的偏移量:
fprintf(stderr, "num2 offset=%d\n", offsetof(RecordStructure, num2));
fprintf(stderr, "num3 offset=%d\n", offsetof(RecordStructure, num3));
答案 1 :(得分:1)
如何在结构中对齐数据可能因编译器以及用于强制进行特定对齐的编译指示而异。
如果此编译器对齐双字边界上的项,则前4个字节num1应与char数组的前4个字节对齐,后4个字节num2与char数组的后4个字节对齐等等。
如果可能,您可以使用调试器在收到数据时检查数据。在发送的数据中,您放置一个特定的十六进制数字序列,以便您可以知道事物是否按照您的想法排列。
因此在PIC上,结构中发送的数据可能是:
RecordStructure myRecord;
myRecord.num1 = 01F2E3D4C;
myRecord.num5 = myRecord.num4 = myRecord.num3 = myRecord.num2 = 0;
然后发送它以查看它的样子。以及num1值是否相同。
如果然后修改数据,例如myRecord.num3 = 1.0,您将能够看到是否排队。
答案 2 :(得分:1)
是。前四个字节将属于num1,然后接下来的四个字节将属于num2等。但是,int和float中的字节顺序是平台和特定于实现的。
然而,有两件事会影响到这一点。一个是对齐,另一个是填充。确保将填充设置为1个字节,以确保变量之间没有内存间隙,并且如果可能,也将对齐设置为1。但是,根据您的编译器和硬件,对齐可能必须是4或8字节的倍数。在这种情况下,您可能需要添加一些填充变量。您可以使用MSVC中的align关键字和GCC中的alignment属性来更改每个结构/变量的默认对齐:
__declspec(align(1)) //MSVC
__attribute__((aligned(1))) //GCC
示例:
#pragma pack(1)
typedef struct{int32 num1;
float num2,num3,num4,num5;
...
}RecordStructure;
typedef union{RecordStructure Record; char Array[48];} My_Rec_Structure;
答案 3 :(得分:1)
这个example显示了如何在两侧使用~RecordStructure~的相同定义,PC(Linux / x86 / gcc)和PIC(18F)。诀窍是使用#ifdef / #define
来支持两个编译器。
#ifdef __cplusplus
# define __PACKED
# define __PACKED2 __attribute__((packed))
#else
# define __PACKED2
#endif
typedef struct __PACKED {
opcodes_t opcode : 8;
union {
osci_config_t set_config_args;
READ_SINGLE_ARGS read_single_args;
SAMPLE_SINGLE_ARGS sample_single_args;
SAMPLE_INTERLEAVED_ARGS sample_interleaved_args;
} args;
} __PACKED2 opcode_decoder_t;