首頁  >  文章  >  後端開發  >  Go和C中的資料結構對齊差異

Go和C中的資料結構對齊差異

WBOY
WBOY轉載
2024-02-09 15:51:091099瀏覽

Go和C中的資料結構對齊差異

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中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除