免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4747 | 回复: 9
打印 上一主题 下一主题

[C] C/C++位段操作 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-02-15 18:12 |只看该作者 |倒序浏览
本帖最后由 duwei211 于 2011-02-16 00:33 编辑

关于位段的赋值的问题:
第一段的汇编代码在5楼,求大侠帮忙,急,在线等
1、
typedef struct  AA
{
        int b1:5;
        int b2:2;
}AA;
void main()
{
        AA aa;
        char cc[100];
         strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");
       memcpy(&aa,cc,sizeof(AA));
        cout << aa.b1 <<endl;
        cout << aa.b2 <<endl;
}

2、struct bit
{   int a:3;
    int  b:2;
    int c:3;
};
int main()
{
  bit s;
  char *c=(char*)&s;
   cout<<sizeof(bit)<<endl;
  *c=0x99;
   cout << s.a <<endl <<s.b<<endl<<s.c<<endl;
     int a=-1;
   printf("%x",a);
  return 0;
}

问题:
个人理解的第一题中:
1、因为AA占四个字节,它取字符串里面的前四个字节,也就是0123,他们都是字符,对应的ASCII为:48,49,50,51:
对应二进制为:000110000 00110001 00110010 00110011
那b1取前5位就是00011  b2取后两位就是00  运行结果是3和0,但是不是这样,大侠们帮下忙啊

第二题:个人理解:
*C的值为0X99,对应二进制也就是10011001,那么a取前三位就是100,b取其后两位就是11,C取后续三位就是001
结果就是-4    -1  1
但是结果也不是这样,大侠帮帮忙啊,急,在线等。对位操作不了解。。

论坛徽章:
1
白羊座
日期:2014-01-14 17:31:01
2 [报告]
发表于 2011-02-15 18:53 |只看该作者
为什么我在linux下执行的结果是:
aa.b1=fffffff0
aa.b2=01

论坛徽章:
0
3 [报告]
发表于 2011-02-15 18:59 |只看该作者
回复 2# gradkid


    我就是搞不懂为什么才来问为什么,上面的结果是我自己理解的,和实际的不同,希望哪个大侠帮帮忙

论坛徽章:
0
4 [报告]
发表于 2011-02-15 20:00 |只看该作者
用objdump反汇编一下,看看指令是怎么操作的。位段的实现不一定像楼主想的那样

论坛徽章:
0
5 [报告]
发表于 2011-02-15 21:59 |只看该作者
本帖最后由 duwei211 于 2011-02-15 22:02 编辑

.file        "AA.c"
        .section        .rodata
.LC0:
        .string        "0123456dssfglfs"
.LC1:
        .string        "%d,%d\n"
        .text
.globl main
        .type        main, @function
main:
        leal        4(%esp), %ecx
        andl        $-16, %esp
        pushl        -4(%ecx)
        pushl        %ebp
        movl        %esp, %ebp
        pushl        %ecx
        subl        $132, %esp
        movl        4(%ecx), %eax
        movl        %eax, -120(%ebp)
        movl        %gs:20, %eax
        movl        %eax, -8(%ebp)
        xorl        %eax, %eax
        movl        $16, 8(%esp)
        movl        $.LC0, 4(%esp)
        leal        -108(%ebp), %eax
        movl        %eax, (%esp)
        call        memcpy
        movl        $4, 8(%esp)
        leal        -108(%ebp), %eax
        movl        %eax, 4(%esp)
        leal        -112(%ebp), %eax
        movl        %eax, (%esp)
        call        memcpy
        movzbl        -112(%ebp), %eax
        addl        %eax, %eax
        sarb        $6, %al
        movsbl        %al,%edx
        movzbl        -112(%ebp), %eax
        sall        $3, %eax
        sarb        $3, %al
        movsbl        %al,%eax
        movl        %edx, 8(%esp)
        movl        %eax, 4(%esp)
        movl        $.LC1, (%esp)
        call        printf
        movl        $0, %eax
        movl        -8(%ebp), %edx
        xorl        %gs:20, %edx
        je        .L3
        call        __stack_chk_fail
.L3:
        addl        $132, %esp
        popl        %ecx
        popl        %ebp
        leal        -4(%ecx), %esp
        ret
        .size        main, .-main
        .ident        "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
        .section        .note.GNU-stack,"",@progbits

论坛徽章:
0
6 [报告]
发表于 2011-02-15 22:03 |只看该作者
上面是它的汇编代码,但是我看不懂,大侠们帮忙解释下重要的部分,谢谢

论坛徽章:
0
7 [报告]
发表于 2011-02-15 23:47 |只看该作者
大侠们,帮帮忙啊,求你们了

论坛徽章:
0
8 [报告]
发表于 2011-02-16 08:18 |只看该作者
首先这是跟CPU有关,x86是little endian,所以位段是从低位向高位分配,字节间是低位字节在前,但字节内部的八个位,写出来的时候,都是从高位写到低位的。

因此 000110000, 所以aa.b1是10000(注意这是一个负数,转换成int时会进行高位扩展),aa.b2是01

论坛徽章:
3
CU大牛徽章
日期:2013-03-14 14:14:08CU大牛徽章
日期:2013-03-14 14:14:26CU大牛徽章
日期:2013-03-14 14:14:29
9 [报告]
发表于 2011-02-16 08:23 |只看该作者
本帖最后由 liugang9931706 于 2011-02-16 10:26 编辑

不敢称大侠,参与讨论下,这里只说说第一题。
没有用编译器验证前,我认为答案是16和1,结果用编译器测试结果是-16和1。
我用的是pc机,是小头的,那么拷贝从低字节开始。
拷贝完成后其实只有低7bit是有效的。因为位段只使用了其中的7bit。
(48)10=(110000)2,其低5位有效,即只取(10000)2=(16)10,?=-16
(48)10=(0110000)2,其低6位7位有效,即只取(01)2=(1)10,?=1
为什么上下转化的结果又区别呢?

论坛徽章:
0
10 [报告]
发表于 2011-02-16 16:27 |只看该作者
aa.b1=fffffff0   低位取值(10000)
aa.b2=01
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP