我已经在C程序中初始化了一个 struct ,并将其附加到共享内存.其 struct 如下:

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

我正在try 从另一个用Golang编写的程序中读取 struct .我已经计算了每个字段在C中占用多少字节,并且在我的Golang struct 中有一个等价的字段,如下所示:

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
}

C中的 struct (DrvSHMTagStruct)的大小是182416,Golang是182412(我的操作系统是基于ARM的).为什么会有区别呢?它们在4个字节中是不同的,有趣的是它们都能完美地工作,在同一个 struct 上读取和写入,没有错误.

显然,我对它进行了搜索,我了解到C编译器在编译过程中执行了大约Data Structure alignment次.因此,有4个字节的差异.但问题是,Golang程序如何正确地从共享内存中读取 struct ,即使它有4个字节的差异?

此外,当我在基于ARM的Linux上运行这些程序时,问题也出现了.在x64的Ubuntu上,它们的大小相同.

推荐答案

这是最后一个成员的填充,Instance.在你的C版本中,它被填充了7个字节.在Go版本中,它被填充了3.区别在于在两个平台上执行sizeof时注意到的4个字节.

为了使它们相同,您可以在C版本中使用#pragma pack(4)或在Go版本中使用#pragma pack(8)(如果它甚至支持打包,搜索表明它不支持)或将filler作为最后一个成员添加到Go struct 中:

Filler1     [7]uint8

C++相关问答推荐

修改pGM使用指针填充2-D数组但不起作用

了解一些CLIPS原语数据类型

在#include中使用C宏变量

如何在C中从函数返回指向数组的指针?

Can函数指针指向C++中具有不同参数连续性的函数

拥有3x3二维数组并访问数组[1][3]等同于数组[2][0]?

将uintptr_t添加到指针是否对称?

为什么我的Hello World EFI程序构建不正确?

有什么方法可以将字符串与我们 Select 的子字符串分开吗?喜欢:SIN(LOG(10))

预处理器宏扩展(ISO/IEC 9899:1999(E)§;6.10.3.5示例3)

这个空指针类型的转换是有效代码还是恶意代码?

赋值两侧的后置增量,字符指针

为什么一个在线编译器拒绝这个VLA代码,而本地的Apple clang却不拒绝;t?

是什么阻止编译器优化手写的 memcmp()?

使用复合文字数组初始化的指针数组

使用fread()函数读取txt文件

无法在线程内用 C 打印?

OpenGL 中的非渐变 colored颜色 变化

Clang 是否为内联汇编生成了错误的代码?

将十六进制值或十进制值分配给 uint16_t 有什么区别?