位域与字节序同时转化的问题

suncs2001 2013-03-06 12:51:15
有个结构体

struct A
{
short data;
short b:6;
short c:3;
short d:7;
}


此结构体在大小端的机器上涉及到位域,应该这样写区分大小端

struct A
{
short data;
#if BIG_ENDIAN
short b:6;
short c:3;
short d:7;
#else
short d:7;
short c:3;
short b:6;
#endif
}

问题在于,因为位域不是一个字节,涉及到大小端时,还需要字节序转化。光定义两套结构体是不行的。
当时的场景是这样的,我不知道怎么转化字节序

如果不需要大小端转化
void rx_func(void*data)
{
A* a;
a = (A*)data;
a->b = 0;
a->c = 0;
a->d = 0;

}
如果需要大小端转化,我需要把结构体里的位域所在的16位做字节序转化,不知道怎么写了。
因为我要转化那16bit,没法写,因为是位域你又不能写 a->b = ntohs((UINT16*)data[0])
...全文
287 点赞 收藏 14
写回复
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
ruanben 2014-07-03
楼主,你搞明白了吗??我最近也特别纠结这一块
回复
mujiok2003 2013-03-07
位域字段一般用不带符号的
回复
mujiok2003 2013-03-07
在序列号和反序列化时分别压缩内存就好了,位域与实现相关,不适合垮进程交换数据。
回复
赵4老师 2013-03-06
引用 7 楼 nice_cxf 的回复:
引用 6 楼 mymtom 的回复:位域不可移植啊! 不是这样的把?iphdr头部就有位域的定义 truct iphdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 ihl:4, version:4; #elif defined (__BIG_ENDIAN_BITFIELD) ……
因为4恰好是8的因数。
回复
nice_cxf 2013-03-06
引用 6 楼 mymtom 的回复:
位域不可移植啊!
不是这样的把?iphdr头部就有位域的定义 truct iphdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 ihl:4, version:4; #elif defined (__BIG_ENDIAN_BITFIELD) __u8 version:4, ihl:4;
回复
ForestDB 2013-03-06
要把这个问题想明白,得把两个概念想明白: byte order,这个比较常见,就是常说的大端,小端; bit field order,这个基本上没人提,就是和字节序类似,称为比特序的概念; 比特序和字节序概念类似,也有大小之分,不过是bit在byte中的分布。 一般只有做IC(即做CPU或者芯片)和做网络协议的人才和比特序打交道, 而做计算机的,一般来说0x5A就是(01011010),是不关心它的bit的顺序的(因为这是实现相关的) 建议参考/usr/include/netinet/tcp.h或者/usr/include/linux/tcp.h中tcp头的定义,其中就有tcp的flag的定义,它确实是比特序相关的一个定义,但是不是字节序相关 把两个概念都弄清楚之后,就会知道,把这两个东西排列组合,混合起来,其实是一种很蠢的做法,因为相当容易弄混。稍微好一点的做法,就是以字节为边界,不要让bit field跨字节,即ip头的定义和tcp头的定义那种做法。
回复
mymtom 2013-03-06
位域不可移植啊!
回复
sinservice 2013-03-06
引用 2 楼 suncs2001 的回复:
哪个不存在,不需要进行网络序转换,之定义两套结构体么
其实不存在,你说出你应用的场景,我来告诉你为什么不存在。
回复
nice_cxf 2013-03-06
引用 3 楼 suncs2001 的回复:
因为字节序与bit序同时存在,位域又跨字节,是涉及到两个转化的。 是不是有移位的方式比较好。
应该不会涉及两个转换把,光修改位域应该就可以了,你测试过么?
回复
赵4老师 2013-03-06
struct A
{
    short data;
#if BIG_ENDIAN
    short b:6;
    short c:3;
    short d:7;
#else
    short d:7;
    short c:3;
    short b:6;
#endif
}
这根本就是错误代码!以下仅供参考:
#include <stdio.h>
#include <stdlib.h>
char buf[17];
union U {
  unsigned short int aa;
  struct S {
    unsigned int bb:7;//(bit 0-6)
    unsigned int cc:6;//(bit 7-12)
    unsigned int dd:3;//(bit 13-15)
  } s;
} u;
void main() {
                //bbbbbbbbbbbbbbbb
                //iiiiiiiiiiiiiiii
                //tttttttttttttttt
                //111111
                //5432109876543210
                //::::::::::::::::
    u.aa=0xE07F;//1110000001111111
    printf("bb==%d,cc==%d,dd==%d\n",u.s.bb,u.s.cc,u.s.dd);
    u.s.bb=0x41;
    u.s.cc=0x21;//dddccccccbbbbbbb
    u.s.dd=5;   //1011000011000001
    printf("aa==0x%04X==%016s(2)\n",u.aa,itoa(u.aa,buf,2));
}
//bb==127,cc==0,dd==7
//aa==0xB0C1==1011000011000001(2)
回复
AnYidan 2013-03-06
位域依赖具体实现
回复
suncs2001 2013-03-06
因为字节序与bit序同时存在,位域又跨字节,是涉及到两个转化的。 是不是有移位的方式比较好。
回复
suncs2001 2013-03-06
哪个不存在,不需要进行网络序转换,之定义两套结构体么
回复
sinservice 2013-03-06
你说的问题根本就不存在。
回复
发动态
发帖子
C语言
创建于2007-09-28

6.3w+

社区成员

C语言相关问题讨论
申请成为版主
社区公告
暂无公告