繁体   English   中英

c结构和字节设置/排序

[英]c structs and byte setting/ ordering

嗨,我正在尝试将一个字节数组读入结构,字节以相反的顺序出现(我的预期)。 有人能帮我理解发生什么事吗?

unsigned char buf[] = {
0x11, 0x22, 0x33, 0x44,
0x55, 0x66, 0x77, 0x88,
0x99, 0xaa, 0xbb, 0xcc
};


typedef struct mystruct {
 uint16_t var1;
 uint16_t var2;
 uint32_t var3;
 uint32_t var4;
} something;


int main(int argc,char **argv){

   printf("sizeof buf: %lu %d \n",sizeof(buf),sizeof(something));
   something *st = (something*)&(buf[0]);
   #define pr(a) printf(#a" %x\n",a)
   pr(st->var1);
   pr(st->var2);
   pr(st->var3);
   pr(st->var4);

   return(0);
}

输出:

sizeof buf: 12 12 
st->var1 2211
st->var2 4433
st->var3 88776655
st->var4 ccbbaa99

我期待的是:st-> var1 1122

这样做也似乎输出了同样的东西?

memcpy(&st->var1,buf,2);
pr(st->var1);

输出:st-> var1 2211

x86 / Linux服务器,gcc版本4.5.3(如果有帮助的话)

谢谢你的帮助。

如果您阅读有关字节序的内容 ,您将看到有两种方法可以在内存中存储长于一个字节的数据。

对于大端系统(如ARM),整数值0x1122存储在内存中(从低地址到高地址) 0x11 0x22 在小端系统(如x86)上,它存储为0x22 0x11

由于数组中的数据存储为“big-endian”,因此您可以获得与您喜欢的小端系统相同的字节顺序。

正如其他人指出的那样,你的主要观察问题是edianness

您访问buf方法是未定义的行为,因为它违反了严格的别名规则,此处类型为punning:

something *st = (something*)&(buf[0]);

如果我使用gcc使用以下参数构建此代码:

-O3 --Wstrict-aliasing=2

我收到以下警告:

main.cpp:22:4: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
    something *st = (something*)&(buf[0]);
    ^

我目前使用的是4.8版本。 涵盖别名规则的C11标准草案的相关部分是6.5/7

正如Joachim和Shafix所说,你可能会遇到填充和字节序问题,但是如果你可以使用#pragma pack这个代码应该可以工作(当小端时交换字节)

#include <stdio.h>
#include <stdint.h>

unsigned char buf[] = {
    0x11, 0x22, 0x33, 0x44,
    0x55, 0x66, 0x77, 0x88,
    0x99, 0xaa, 0xbb, 0xcc
};

typedef struct mystruct {
    uint16_t var1;
    uint16_t var2;
    uint32_t var3;
    uint32_t var4;
} something;

static uint16_t swap16(uint16_t val)
{
    return ((val >> 8) & 0xFF) | ((val << 8) & 0xFF00);
}

static uint32_t swap32(uint32_t val)
{
    uint16_t v1 = swap16((uint16_t) val);
    uint16_t v2 = swap16((uint16_t) (val >> 16));
    return (v1 << 16) | (v2);
}

int main(void)
{
    printf("sizeof buf: %zu %zu \n", sizeof(buf), sizeof(something));
    something *st = (something*)&(buf[0]);

    #define pr(a) printf(#a" %x\n", a)

#if __BYTE_ORDER == __LITTLE_ENDIAN 
    st->var1 = swap16(st->var1);
    st->var2 = swap16(st->var2);
    st->var3 = swap32(st->var3);
    st->var4 = swap32(st->var4);
#endif

    pr(st->var1);
    pr(st->var2);
    pr(st->var3);
    pr(st->var4);

    return(0);
}

编辑:

#pragma pack将导致预处理器丢弃结构成员的预定对齐,因此不会插入填充字节,您可以按如下方式定义结构:

#pragma pack(push, 1) // exact fit - no padding
typedef struct mystruct {
    uint16_t var1;
    uint16_t var2;
    uint32_t var3;
    uint32_t var4;
} something;
#pragma pack(pop) //back to whatever the previous packing mode was

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM