Maison  >  Article  >  développement back-end  >  Différences d’alignement de la structure des données dans Go et C

Différences d’alignement de la structure des données dans Go et C

WBOY
WBOYavant
2024-02-09 15:51:091099parcourir

Différences d’alignement de la structure des données dans Go et C

l'éditeur php Xigua est là pour vous présenter les différences d'alignement de la structure des données en Go et C. Dans les langages de programmation, l'alignement de la structure des données est une méthode d'alignement de la mémoire utilisée pour améliorer l'efficacité de l'accès à la mémoire. Cependant, il existe quelques différences entre Go et C en termes d'alignement de la structure des données. En langage C, l'alignement est contrôlé via les paramètres du compilateur, tandis qu'en langage Go, l'alignement est effectué automatiquement par le compilateur. Cette différence peut provoquer des erreurs d’accès mémoire dans Go lorsque le code est écrit en C. Par conséquent, il est très important que les développeurs comprennent les différences d’alignement de la structure des données en Go et en C.

Contenu de la question

J'ai initialisé une structure dans mon programme C et je l'ai attachée à la mémoire partagée. La structure est la suivante :

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

J'essaie de lire une structure d'un autre programme écrit en Golang. J'ai calculé le nombre d'octets pris par chaque champ en C et j'ai un champ équivalent dans ma structure Golang comme ceci :

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
}
La taille de

structure (DrvSHMTagStruct) est 182416 en C et 182412 en Golang (mon système d'exploitation est basé sur ARM). Alors pourquoi y a-t-il une telle différence ? Ils sont différents de 4 octets et ce qui est intéressant est qu'ils fonctionnent tous les deux correctement, lisant et écrivant sur la même structure sans erreur.

En cherchant évidemment, j'ai appris que les compilateurs C effectuent un certain alignement de la structure des données lors de la compilation. Il existe donc une différence de 4 octets. Mais la question est : comment un programme Golang peut-il lire correctement une structure à partir de la mémoire partagée même s'il y a une différence de 4 octets ?

De plus, le problème survient lorsque j'exécute le programme sur Linux basé sur ARM. Ils ont la même taille sur Ubuntu x64.

Solution de contournement

Il s'agit des 4 octets remarqués lorsque le dernier membre Instance 的填充。在你的 C 版本中,它用 7 个字节填充。在 Go 版本中,它用 3 填充。区别在于您在两个平台上执行 sizeof est ajouté.

Pour les rendre identiques, vous pouvez utiliser #pragma pack(4) 或在 Go 版本中使用 #pragma pack(8) dans la version C (si elle prend même en charge le packaging, la recherche suggère que ce n'est pas le cas) ou ajouter un remplissage comme dernier membre de la structure Go :

Filler1     [7]uint8

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer