免费注册 查看新帖 |

Chinaunix

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

1 还是 -1 ? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-07-14 20:52 |只看该作者 |倒序浏览
最近在看位序,即bit order。(当然我的问题可能与之无关,也可能有关,我也不知道)
  1. #include <stdio.h>  

  2. //#define BYTE unsigned char
  3. #define BYTE char
  4. typedef struct
  5. {
  6.         BYTE a:1;
  7.         BYTE b:1;
  8.         BYTE c:1;
  9.         BYTE d:1;
  10.         BYTE e:1;
  11.         BYTE f:1;
  12.         BYTE g:1;
  13.         BYTE h:1;
  14. }TestBit;


  15. int main(int argc, char* argv[])
  16. {
  17.         char c = 0x96; /* 10010110 */
  18.         TestBit *q = NULL;
  19.        
  20.         q = (TestBit *)&c;
  21.         printf("q->a = %d\n", q->a);
  22.         printf("q->b = %d\n", q->b);
  23.         printf("q->c = %d\n", q->c);
  24.         printf("q->d = %d\n", q->d);
  25.         printf("q->e = %d\n", q->e);
  26.         printf("q->f = %d\n", q->f);
  27.         printf("q->g = %d\n", q->g);
  28.         printf("q->h = %d\n", q->h);

  29.     return 0;
  30. }
复制代码
我的问题是在这两个define这里。
当用#define BYTE unsigned char时,输出是:
[pwp@localhost bit_order]$ ./bit_order
q->a = 0
q->b = 1
q->c = 1
q->d = 0
q->e = 1
q->f = 0
q->g = 0
q->h = 1

当时当用#define BYTE char时,输出是:
[pwp@localhost bit_order]$ ./bit_order
q->a = 0
q->b = -1
q->c = -1
q->d = 0
q->e = -1
q->f = 0
q->g = 0
q->h = -1

为什么会是-1呢?

论坛徽章:
0
2 [报告]
发表于 2011-07-14 21:13 |只看该作者
回复 1# panweiping

    感觉有点怪怪的
    为什么 c 不定义成TestBit类型

论坛徽章:
0
3 [报告]
发表于 2011-07-14 21:29 |只看该作者
那怎么赋值呢?
TestBit d = 0x96; /* 10010110 */

编译器报bit_order.c:33:2: error: invalid initializer

当然可以用 TestBit d = { .a=0, .b=1};这样赋值,但是这不是重点,也不是问题的本质所在吧。

论坛徽章:
0
4 [报告]
发表于 2011-07-14 21:39 |只看该作者
有符号数,最高位是1,是负数没什么疑问的啊

论坛徽章:
0
5 [报告]
发表于 2011-07-14 21:40 |只看该作者
回复 3# panweiping


    -1说明char 类型是signed

论坛徽章:
0
6 [报告]
发表于 2011-07-15 00:20 |只看该作者
drangon 的回答大体靠谱。

在目前流行的编码系统中,判断一个有符号数的正负根据其最高位,那么只有一个位的数而言,那个唯一存在的位同时是其最高位,具体到你的例子,q->b 是一个只有一个位的数,其唯一的位也就是最高位是 1,所以它是负数。换一个角度,n 个位可以表示的有符号数的范围是:[-2^(n-1), 2^(n-1) - 1],譬如:8 个 bit 可以表示的数的范围是:[-128, 127],那么一个位能表示的有符号数范围是什么呢?代入刚才的公式,范围是:[-1, 0],这下释怀了吧。

结论是:单比特的有符号位段不宜直接作为整数使用。

论坛徽章:
0
7 [报告]
发表于 2011-07-15 07:04 |只看该作者
本帖最后由 KBTiller 于 2011-07-15 07:29 编辑

8.5.2  如何定义位段
在结构体或联合体类型中定义位段成员的一般方法是:
数据类型 [成员名称]:数据宽度;
这里的数据类型可以是“signed int”、“unsigned int”、“int”,这几种类型是标准规定的,此外C99还允许_Bool类型。有些编译器在此基础上还允许其他类型,比如char类型
数据宽度必须是一个非负的整数类型常量表达式。这个数据宽度不允许过大。一般来说,通常以计算机的字长为限。
成员名称是可以省略的,但这样的成员在代码中是无法引用的,其作用是在数据之间起到间隔或填充的作用。这样的位段通常被叫做无名位段。
如果一个无名位段的数据宽度为0,表示的含义是下一位段需要存放到下一个“存储单元”。但这种“存储单元”究竟以什么为单位很难一概而论,通常是由编译器自行定义的,大多数情况下是指一个计算机字。
位段成员同样不能跨越“存储单元”的边界,如果遇到一个“存储单元”中剩余的位数不够存储下一个位段的情况,编译器会将这个字段安排在下一个“存储单元”之中。
8.5.3  位段的性质
位段的值(右值)可以参加运算,运算时一律转换为“signed”类型或“unsigned”类型,但是“int”类型的位段很难说是“signed”类型还是“unsigned”类型。
如果编译器规定“char”类型为“signed ”类型,那么“int”类型的位段也是“signed”类型;反之,如果编译器规定“char”类型为“unsigned ”类型,那么“int”类型的位段也是“unsigned”类型。
位段成员可以被赋值,但基本上无法把位段成员当作左值,因为无法给出位段的位置的C语言表达。位段无法作为左值参与“sizeof”、“&”等左值才能参与的运算,但可以进行“++”、“--”这种运算。
由于C语言无法表达位段的内存位置,所以也不可以构造位段数组。
可以用%d、%x、%u和%o等格式字符,以整数形式输出位段的值。但是由于位段成员无法进行一元“&”运算,所以无法直接通过调用scanf()函数输入位段的数据。

http://book.chinaunix.net/showart.php?id=8555

char位段不属于标准规定的用法,只是某些编译器支持
我认为char位段的性质和int位段的性质一样
其为signed还是unsigned取决于“char”类型是否为“signed ”类型(这一点是我的推测,究竟如何可能还是要看编译器的文档)

论坛徽章:
0
8 [报告]
发表于 2011-07-15 09:11 |只看该作者
释怀了。

谢谢大家。

论坛徽章:
0
9 [报告]
发表于 2011-07-15 10:34 |只看该作者
>>其为signed还是unsigned取决于“char”类型是否为“signed ”类型(这一点是我的推测,究竟如何可能还是要看编译器的文档)

C标准里没有规定char是否有符号。这个取决于编译器实现。
事实上如果想表示取值范围在[-128, 127]的整数,应使用signed char,想表示取值范围在[0, 255]的整数,应使用unsigned char。
只有当要表示可打印的单字节字符时,才应该使用char。

论坛徽章:
0
10 [报告]
发表于 2011-07-15 10:36 |只看该作者
回复 9# 狗气球


    完全同意这个补充
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP