标题:明解 C 中一个例题,窥探整数内部 ,很不明白,求大神指教。
只看楼主
stoneshing
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2014-8-18
结帖率:100%
 问题点数:0 回复次数:10 
明解 C 中一个例题,窥探整数内部 ,很不明白,求大神指教。
程序目的:显示 unsigned 型内部的位串

#include <stdio.h>

int count_bits (unsigned x)
{
int count =0;
while (x){
if (x &1U) count++;
x>>=1;
}
return (count);
}//书中说这是返回整数X中设置的位数。

int int_bits()
{
return (count_bits(~0u));
}

void print_bits (unsigned x)
{
int i;
for (i=int_bits()-1;i>=0;i--)
putchar (((x>>i)&1u) ? '1':'0');

}

int main ()
{
unsigned nx;
printf("请输一个非负整数:");
scanf("%u",&nx);
print_bits (nx);
putchar ('\n');
return 0;
}


请大神详细,举例说明啊,谢谢
搜索更多相关主题的帖子: include return count 
2014-08-31 14:49
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
这都要详解,还怎么得了。

授人以渔,不授人以鱼。
2014-08-31 16:18
erty1001
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:4
帖 子:331
专家分:1433
注 册:2014-8-31
得分:0 
简单说说:
int count_bits (unsigned x)   //这里下面调用的时候代入的是 ~0u 也就是 11111111111111111111 很多个1
                                                          取决于当前计算机环境
{
int count =0;
while (x){                   //   x=11111111111111111111111111 执行循环
if (x &1U) count++;           //   111111111111111&000000000000001 不为零  count ++         
x>>=1;                        // x=x>>1;    x循环右移 x=01111111111111111
}
return (count);               //最终输出来 ~0u总共有多少个1 即位宽
}//书中说这是返回整数X中设置的位数。



接下来

int int_bits()
{
return (count_bits(~0u));    //看上面一段 我不多说了  反正返回值 是当前计算机usinged int 位宽
                              //不妨我们假设是32位平台  返回值是32
}

然后:
void print_bits (unsigned x)      //由主函数 输入x=“00000000000000000010100101010101010010101” 共32位
                                  //注意这里01是计算机自动转换的 其实输入的是x=565412521
{
int i;
for (i=int_bits()-1;i>=0;i--)             //这里  int_bits()=32
putchar (((x>>i)&1u) ? '1':'0');          //先输入x=“00000000000000000010100101010101010010101”的最高位
                                          //所以先使劲右移很多位 x=00000000000000000000000000000,逐次计算
                                             各位,x>>i既是生成个临时变量是x的右移i次的结果   ,
                                              (x>>i)&1u   检查这个临时变量的个位数字是不是1 是就输出1不是输出0

}
2014-08-31 17:00
erty1001
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:4
帖 子:331
专家分:1433
注 册:2014-8-31
得分:0 
简单说说:
int count_bits (unsigned x)   //这里下面调用的时候代入的是 ~0u 也就是 11111111111111111111 很多个1
                                                          取决于当前计算机环境
{
int count =0;
while (x){                   //   x=11111111111111111111111111 执行循环
if (x &1U) count++;           //   111111111111111&000000000000001 不为零  count ++         
x>>=1;                        // x=x>>1;    x循环右移 x=01111111111111111
}
return (count);               //最终输出来 ~0u总共有多少个1 即位宽
}//书中说这是返回整数X中设置的位数。



接下来

int int_bits()
{
return (count_bits(~0u));    //看上面一段 我不多说了  反正返回值 是当前计算机usinged int 位宽
                              //不妨我们假设是32位平台  返回值是32
}

然后:
void print_bits (unsigned x)      //由主函数 输入x=“00000000000000000010100101010101010010101” 共32位
                                  //注意这里01是计算机自动转换的 其实输入的是x=565412521
{
int i;
for (i=int_bits()-1;i>=0;i--)             //这里  int_bits()=32
putchar (((x>>i)&1u) ? '1':'0');          //先输入x=“00000000000000000010100101010101010010101”的最高位
                                          //所以先使劲右移很多位 x=00000000000000000000000000000,逐次计算
                                             各位,x>>i既是生成个临时变量是x的右移i次的结果   ,
                                              (x>>i)&1u   检查这个临时变量的个位数字是不是1 是就输出1不是输出0

}
2014-08-31 17:00
stoneshing
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2014-8-18
得分:0 
回复 4 楼 erty1001
谢谢,我打印出来,一步一步看,太感谢了。
2014-08-31 18:37
stoneshing
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2014-8-18
得分:0 
回复 4 楼 erty1001
感谢erty1001

研究了好久,有点感觉 ,但有以下几点不明白:

1:count_bits(~0u)  这个返回值 ,应该是程序自动计算出不同计算机的位宽吧?以后求此类问题,都可套用此函数吧?如果是64位,是表示CPU 是64位,还是操作系统是64位?

2:for (i=int_bits()-1;i>=0;i--)   这里i=int_bit()-1;这个表达式不明白,i 表示位移的位数,是不是由于unsigned x,最高位符号位是0,不能移动? 如0111向右移4位,在表达式
((x>>i)&1u) ? '1':'0' 中,和移三位没有区别啊。 若表达式改为 ((x>>i)&1u) ? '0':'1',则符号发生了变化。有点凌乱。

3:void print_bits (unsigned x)      //由主函数 输入x=“00000000000000000010100101010101010010101” 共32位
                                  //注意这里01是计算机自动转换的 其实输入的是x=565412521

是否只有涉及到位运算符&,如 123&456,计算机都会自动把十进制123,456转化成相应的二进制 ?

谢谢。
2014-09-01 08:57
erty1001
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:4
帖 子:331
专家分:1433
注 册:2014-8-31
得分:0 
1:count_bits(~0u)  这个返回值 ,应该是程序自动计算出不同计算机的位宽吧?以后求此类问题,都可套用此函数吧?如果是64位,是表示CPU 是64位,还是操作系统是64位?
我理解的是 (是程序自动计算出不同计算机的位宽) 以后可以利用这种方法。
如果结果是64 表示当前编译,对unsigned int 型 编译成了 64=8(字节)*8(bit) 只能说明如此  ,至于CPU 是64位,还是操作系统 关系不是太大
2:for (i=int_bits()-1;i>=0;i--)   这里i=int_bit()-1;这个表达式不明白,i 表示位移的位数,是不是由于unsigned x,最高位符号位是0,不能移动? 如0111向右移4位,在表达式
((x>>i)&1u) ? '1':'0' 中,和移三位没有区别啊。 若表达式改为 ((x>>i)&1u) ? '0':'1',则符号发生了变化。有点凌乱。
首先 unsigned int  最高位有可能是1 未必都是0的。
简单说说呀:我们假设前面所说的是8位的unsigned int 的编译环境
x=1011 0101  (由于假设是8位环境)
我们想顺序输出  1  0  1  1   0  1  0  1 怎么处理呢
第一我们输出x最高位 1:
    先把x 右移操作 1次 01011010
    再把x 右移操作 1次 00101101
    再把x 右移操作 1次 00101101
    。。。。。。。 一共移多少次呢    8-1次  (这里可以解释i=int_bits()-1)
    结果是x=           00000001    (末尾的1 表示x之前最高位是1)
第二我们输出x次高位 0:
    先把x 右移操作 1次 01011010
    再把x 右移操作 1次 00101101
    再把x 右移操作 1次 00101101
    。。。。。。。 一共移多少次呢    8-1-1次  (这里可以解释i--)
    结果是x=           00000010    (末尾的0 表示x之前次高位是0)

其他的不多说了

关于这个 ((x>>i)&1u) ? '1':'0'
    x向右移动i位 & 1u  就是说 按位进行与运算  
        假设 x=1010 1001 & y=0000 0001  结果只保留x的最低位。
             结果是个临时变量 temp=0000  0001  (保留x最低位的特质)   
    temp ? '1':'0'   这个是个冒号表达式,前面的temp != 0  这个表达式结果就是1  前面temp == 0 这个表达式就是0

 
若表达式改为 ((x>>i)&1u) ? '0':'1',则符号发生了变化。有点凌乱。

那样做的话 结果就是0 1 互换 ,原来是1 生成了0 原来是0 则变成了1


3:void print_bits (unsigned x)      //由主函数 输入x=“00000000000000000010100101010101010010101” 共32位
                                  //注意这里01是计算机自动转换的 其实输入的是x=565412521

是否只有涉及到位运算符&,如 123&456,计算机都会自动把十进制123,456转化成相应的二进制 ?

计算机内部是按照x=“00000000000000000010100101010101010010101” 储存的
涉及到位运算符&,我们人工解释代码的时候 需要手动将10 16进制翻译成二进制。



 
2014-09-01 09:58
erty1001
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:4
帖 子:331
专家分:1433
注 册:2014-8-31
得分:0 
    先把x 右移操作 1次 01011010
    再把x 右移操作 1次 00101101
    再把x 右移操作 1次 00101101

不好意思 有笔误
应该是
    先把x 右移操作 1次 01011010
    再把x 右移操作 1次 00101101
    再把x 右移操作 1次 00010110

等等
2014-09-01 09:59
stoneshing
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2014-8-18
得分:0 
回复 8 楼 erty1001
谢谢,我想还是要先习惯编程思维,我多看看。
2014-09-02 23:06
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
编译器在编译的时候就已经确定了数据类型的位数,不用在运行时去求,何况这还是内置基础数据类型。

授人以渔,不授人以鱼。
2014-09-03 12:58



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-435530-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.383333 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved