和你说一句关键的(别告我你整个程序一句都看不懂):
P1=0xfe;
0xfe是十六进制表示的数,二进制就是1111 1110,通过你的程序和相关注释可以看出,硬件上你有8个led灯连接P1口,且这些led是低电平亮。P1=0xfe(1111 1110)也就是表示七个灯灭,一个灯亮。接下来的代码就是让P1数据0xfe左移且低位补1,移一次就是1111 1101,、两次就是1111 1011,三次是1111 0111。。。以此类推,可以看出它是0由最低位到最高位依次移过去的,而刚说了0表示led亮,这也就是led从一边到另一边依次点亮的效果。
后面的代码按我上面说的自己理解,完全对你解释太麻烦,对你也没多大好处,只有你自己理解了才能学好单片机
#include <stdioh>
#include <stringh>
int main()
{
char data[33];
int dota[33];
int i, j, num, len;
gets(data);
len = strlen(data);
for (i = 0; i <= len; i++)
{
dota[i] = (int)data[i] -'0';
}
num = dota[0];
for (j = 1; j < len; j++)
{
num = num 2 + (int)dota[j];
}
printf("%d\n", num);
}
//改了一下,自己看吧!不明可以问的!
下面是三种方式:
①通过模2除2(%2、/2)的方法
num%2——取出二进制的最后一位
num/2——右移去掉二进制的最后一位
通过while循环,依次取出二进制的最后一位数字判断是否为1,若为1则count++,while(num)只有当num变为0时循环结束。
问题:在测试-1出现bug,-1的二进制中应该有32个1,输出却为0。我们将-1带入代码中发现-1%2=0,count不增,然后-1/2=0,循环结束,故输出count的值为0。
解决方案:将变量num的数据类型改为unsigned int (无符号整型),此时表示的是正的整型的最大值,所以当num=-1时,表示二进制为32个1的正数,通过循环可以输出正确的个数。
②通过右移 *** 作符(>>)、按位与 *** 作符(&)实现
Example:当num=10(1010),通过右移 *** 作num>>i,二进制向右移动i位。
//i=0,num>>0,右移0位,此时(1010)&(0001)=0
//i=1,num>>1,右移1位,此时(0101)&(0001)=1,count++
//i=2,num>>2,右移2位,此时(0010)&(0001)=0
//i=3,num>>3,右移3位,此时(0001)&(0001)=1,count++
……
因为二进制共32位,所以循环要执行32次后结束,得到count为2。
缺点:不够高效,必须循环32次。
③通过按位与 *** 作符(&)巧妙运算实现
Example: 当num=15时,
1//num&(num-1)=(1111)&(1110)=(1110)
2//num&(num-1)=(1110)&(1101)=(1100)
3//num&(num-1)=(1100)&(1011)=(1000)
4//num&(num-1)=(1000)&(0111)=0 ,循环停止。共执行4次while循环。
扩展资料
一、指定的某一位数置1
宏 #define setbit(x,y) x|=(1<<y)
二、指定的某一位数置0
宏 #define clrbit(x,y) x&=~(1<<y)
三、指定的某一位数取反
宏 #define reversebit(x,y) x^=(1<<y)
四、获取的某一位的值
宏 #define getbit(x,y) ((x) >> (y)&1)
是按2进制代码的同位进行运算。例如1010和1101这2个2进制数:
按位与为:
1010
1101
=
1000对应为同为1时是1,否则为0
按位或为:
1010
1101
=
1111只要同位的两个全为零时得零,否则为1
1、电脑中存放的数(二进制)都是用补码表示的。
先说说原码。
把一个数的绝对值用二进制表示,然后在最高位添上一个符号位(正数添0,负数添1),得到的就是原码。
比如对于int型整数来说,字长16位,表示十进制数123和-234。
123表示为二进制为111
1011,补至16位即0000
0000
0111
1011,因为是正数,所以最高位(从左数第一位)写0。
所以123原码就是0000
0000
0111
1011
234表示为二进制为1110
1010,补至16位即0000
0000
1110
1010,因为是负数,所以最高位改为1
所以-234的原码就是1000
0000
0111
1011
整数X(二进制)补码的表示规则如下
若X大于等于0,则补码与源码相同;
若X小于0,则补码为-X的原码各位取反,然后再加1。
比如上面的-234,234的原码是0000
0000
0111
1011,欲求它的补码
先各位取反,得1111
1111
1000
0100,
再加1得1111
1111
1000
0101
同理,-1在计算机中的表示形式,首先1的原码为0000
0000
0000
0001
各位取反得1111
1111
1111
1110
再加1得1111
1111
1111
1111。
八进制和十六进制其实就是二进制的简略形式,因为一大堆的0和1很容易看错。
八进制就是把二进制数从低位(右边)开始,每3个数字一组对应到这三个数所对应的十进制数。因为是每三个数字一组,所以只有0-7这些数字有对于,8和9不会出现。
把1111
1111
1111
1111按每3个数一组分组,得到
1
111
111
111
111
111,最高位的1补上两个0
001
111
111
111
111
111
写成八进制就是177777。
同样十六进制也是,不过是4个数字一组。因为4个数字有16种组合,大于9的部分如下表示
二进制数
-
十进制数
-
十六进制数
1010
-
10
-
A
1011
-
11
-
B
1100
-
12
-
C
1101
-
13
-
D
1110
-
14
-
E
1111
-
15
-
F
所以1111
1111
1111
1111写成十六进制数就是FFFF。
至于那个字符代码,没有什么背的必要。都是查表。用到的时候看两眼就记得了,用完了就忘了。
输出结果是由两条printf()语句得出的:
printf("%d→%u\n",b,a);
其中%d是十进制,所以%d就输出-1,然后→照写,最后%u是无符号数,把-1写成二进制形式:1000 0000 0000 0001(最高位为符号位,因为是负数,所以最高位为1),因为在计算机里数字都是用补码表示的,所以把以上的二进制(原码)写成补码为:(1111 1111 1111 1111)2=(65535)10(补码=反码+1)
所以最后输出结果为:-1→65535
printf("%d→%u\n",b,a);
因为b=a,而a=65534u,当我们用二进制表示时可以发现最高位为1,说明此数为负数,表示为:1111 1111 1111 1110此时为补码,反码=补码-1,为:1111 1111 1111 1101,再把反码变成原码(符号位不变)为:1000 0000 0000 0010,这个二进制数表示-2
所以第二个输出语句的结果为:-2→65534
如果n为13,二进制为1101
那么程序执行是这样的:
dtob(13)
{
13的二进制为1101,去掉最后一位后变成110,即13/2=6,进行dtob(6)
输出最后一位1,即13%2=1
}
dtob(6)
{
13的二进制为110,去掉最后一位后变成11,即6/2=3,进行dtob(3)
输出最后一位0,即6%2=0
}
dtob(3)
{
13的二进制为11,去掉最后一位后变成1,即3/2=1,进行dtob(1)
输出最后一位1,即3%2=1
}
dtob(1)
{
13的二进制为1,去掉最后一位后没有了
输出最后一位1,即3%2=1
}
最后就是
dtob(13)
{
dtob(6)
{
dtob(3)
{
dtob(1)printf 1 -------1
printf 1 --------------1
}
printf 0 -------------------0
}
printf 1 -----------------------1
}
以上就是关于C语言C51单片机花样流水灯程序分析注释全部的内容,包括:C语言C51单片机花样流水灯程序分析注释、C语言。编写一个程序,输入一个二进制的字符串(长度不超过32),然后计算出相应的十进制整数,并打印。、c语言中如何提取二进制数中的某一位等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)