php小编西瓜在这里为大家介绍一下Go和C中的数据结构对齐差异。在编程语言中,数据结构对齐是为了提高内存访问效率而进行的一种内存对齐方式。然而,Go和C在数据结构对齐方面存在一些差异。在C语言中,对齐是通过编译器的设置来控制的,而在Go语言中,对齐则是由编译器自动完成的。这种差异可能会导致在使用C语言编写的代码在Go语言中出现内存访问错误。因此,了解Go和C中的数据结构对齐差异对于开发人员来说是非常重要的。
我已经在我的 C 程序中初始化了一个结构并将其附加到共享内存。结构如下:
#define DrvMaxTag 1024 #define DrvMaxStr 128 #define StructLEN 32 typedef struct TagTypeStruct { unsigned char IO; unsigned char Drv; unsigned char Class; unsigned char Group; }TagTypeStruct; typedef struct IEC_DT { long int tv_Sec; long int tv_nSec; }IEC_DT; typedef struct DrvSHMTagStruct { char TagName[DrvMaxTag][DrvMaxStr]; double TagValue[DrvMaxTag]; double OldValue[DrvMaxTag]; unsigned int TagStatus[DrvMaxTag]; unsigned int OldStatus[DrvMaxTag]; long long TagControl[DrvMaxTag]; IEC_DT TagValueDT[DrvMaxTag]; TagTypeStruct TagType[DrvMaxTag]; int DrvAddr[DrvMaxTag]; unsigned char LogFlag[DrvMaxTag]; unsigned char Freeze[DrvMaxTag]; int LogicState; char DrvPath[DrvMaxStr]; int TagQuantity; unsigned char Instance; }DrvSHMTagStruct;
我正在尝试从另一个用 Golang 编写的程序中读取结构。我计算了 C 中每个字段占用的字节数,并在我的 Golang 结构中拥有一个等效字段,如下所示:
const StructLEN = 32 const DrvMaxTag = 1024 const DrvMaxStr = 128 type TagTypeStruct struct { IO uint8 Drv uint8 Class uint8 Group uint8 } type IEC_DT struct { tv_Sec int32 tv_nSec int32 } type DrvSHMTagStruct struct { TagName [DrvMaxTag][DrvMaxStr]byte TagValue [DrvMaxTag]float64 OldValue [DrvMaxTag]float64 TagStatus [DrvMaxTag]uint32 OldStatus [DrvMaxTag]uint32 TagControl [DrvMaxTag]int64 TagValueDT [DrvMaxTag]IEC_DT TagType [DrvMaxTag]TagTypeStruct DrvAddr [DrvMaxTag]int32 RetainFlag [DrvMaxTag]uint8 Freeze [DrvMaxTag]uint8 LogicState int32 DrvPath [DrvMaxStr]uint8 TagQuantity int32 Instance uint8 }
结构体(DrvSHMTagStruct
)的大小在C中是182416,在Golang中是182412(我的操作系统是基于ARM的)。那么为什么会有这样的差异呢?它们有 4 个字节不同,有趣的是它们都工作得很好,在相同的结构上读写,没有错误。
正如我显然搜索过的那样,我了解到 C 编译器在编译过程中会进行一些数据结构对齐。因此,有 4 个字节的差异。但问题是,即使有 4 个字节的差异,Golang 程序如何正确地从共享内存中读取结构呢?
此外,当我在基于 ARM 的 Linux 上运行程序时,问题出现了。它们在 x64 Ubuntu 上的大小相同。
这是最后一个成员 Instance
的填充。在你的 C 版本中,它用 7 个字节填充。在 Go 版本中,它用 3 填充。区别在于您在两个平台上执行 sizeof
时注意到的 4 个字节。
为了使它们相同,您可以在 C 版本中使用 #pragma pack(4)
或在 Go 版本中使用 #pragma pack(8)
(如果它甚至支持打包,搜索建议它没有)或添加一个填充符作为 Go 结构的最后一个成员:
Filler1 [7]uint8
以上是Go和C中的数据结构对齐差异的详细内容。更多信息请关注PHP中文网其他相关文章!