首页 > 解决方案 > 将结构从小端转换为大端

问题描述

我的问题是将指向结构的指针从小端转换为大端,以便我可以将其发送到网络,因为我的结构是 12 字节或 92 位,所以我不能应用任何给定的标准或非标准函数。

我正在尝试在我的 linux 系统上实现 GTPv1U,因为我的结构指针是 96 位的,所以我试图将它分成三个 32 位的块,然后进行转换,但我无法打破它,我也怀疑这不是正确的方法

我的结构代码

typedef struct  __attribute__((__packed__)) GTPv1Uheader{
    UInt8  version              :3;
    UInt8  ProtocolTypeFlag     :1;
    UInt8  Spare                :1;
    UInt8  ExtensionFlag        :1;
    UInt8  SequenceNumberFLAG   :1;
    UInt8  NpduNumberFlag       :1;
    UInt8  MessageType;
    UInt16 Length;
    UInt32 TEID;                    
    UInt16 SequenceNumber;
    UInt8  NPDUNumber;
    UInt8  NextExtensionheader;
} GTPv1UheaderT;

赋值

GTPv1UheaderT * IntializeGTP(){
    GTPv1UheaderT *GTPv1UheaderP;
    GTPv1UheaderP = malloc(sizeof(GTPv1UheaderT));
    memset(GTPv1UheaderP, 0, (sizeof(GTPv1UheaderT)));
    GTPv1UheaderP->version              = 0x1;
    GTPv1UheaderP->ProtocolTypeFlag     = 0x1;
    GTPv1UheaderP->Spare                = 0x0;
    GTPv1UheaderP->ExtensionFlag        = 0x0;
    GTPv1UheaderP->SequenceNumberFLAG   = 0x1;
    GTPv1UheaderP->NpduNumberFlag       = 0x0;
    GTPv1UheaderP->MessageType          = 0x01;
    GTPv1UheaderP->Length               = 0x000C;
    GTPv1UheaderP->TEID                 = 0x00000001;
    GTPv1UheaderP->SequenceNumber       = 0x0000;
    GTPv1UheaderP->NPDUNumber           = 0x00;
    GTPv1UheaderP->NextExtensionheader  = 0x00;
    return GTPv1UheaderP;
}

预期输出:32 01 00 0C 00 00 00 01 00 00 00 00

实际输出:49 01 0C 00 01 00 00 00 00 00 00 00

编辑:这是交换功能

long s; 
unsigned char k;
k=(unsigned char)GTPv1UheaderP;
s=(unsigned int)k;
s=ntohl(s);
printf("%ld\n",s);

我知道这行不通,因为我的 long 是 32 位,而指针是 96 位。任何其他解决方案

标签: cendianness

解决方案


将一个整体struct从/转换为小端或大端没有意义,因为字节序是多字节标量类型表示的属性,例如单个UInt16or UInt32。将 a 转换struct为其“在线表示”时,您一次通过一个元素,并逐个元素地准备其表示。

位字段代表一种特殊情况,因为它们的顺序是实现定义的。您需要按照您喜欢的顺序将它们序列化为单个字节。使用hton/ntoh函数对单个多字节元素进行转换,即LengthTEID


推荐阅读