在C语言中,移位运算是双目运算符,属于位运算的范畴,它分为左移(<<)运算和右移(>>)运算两种。
对于左移运算,运算符的左边是移位对象,右边是整型表达式,代表左移的位数。左移时,无论移位对象是有符号数还是无符号数,都是右端(低位)补0,左端(高位)移出的部分舍弃。左移时,如果左端移出的部分不包含二进制数1,则每左移1位相当于移位对象乘以2,左移2位相当于移位对象乘以4。因此当左移后移出部分不包含1时,可以用这一特性代替乘法运算,以加快运算速度。如果移出部分包含二进制数1时,这一特性就不适用。
掌握移位运算的关键是牢记对于有符号数和无符号数的处理差异。对于左移运算,无论移位对象是有符号数(包括正数和负数)还是无符号数,都是低位补0,高位舍弃。而右移运算则较复杂,若移位对象是无符号数,是高位补0,低位舍弃;若移位对象是有符号数,则要视其正负而定:对于正数(最高位为0),是高位补0,低位舍弃,对于负数(最高位为1),则是高位补1,低位舍弃。可以总结为:左移不分正负,左丢弃右补零;右移要分正负,右丢弃左补高(极代表正负,正补0,负补1)。
为了扩大视野,增加学习编程的兴趣,我参阅了有关书籍,整理了几种排序法,写出来同大家共勉。
C语言移位运算:
让我们来看一个例子,下面的表给出了对某些实例8位数据做不同的移位操作得到的结果。
参数X
[0110 0011] [1001 0101]
X
[0011 0000] [0101 0000]
X>>4(逻辑右移)
[0000 0110] [0000 1001]
X>>4(算术右移)
[0000 0110] [1111 1001]
斜体的数字表示的是最右端(左移)或最左端(右移)填充的值。可以看到除了一个条目之外,其他的都涉及填充0。唯一的例外是算术右移[10010101]的情况。因为操作数的最高位是1,填充的值就是1。
C语言标准并没有明确定义应该使用哪种类型的右移。对于无符号数据(也就是以限定词unsigned声明的整型对象),右移必须是逻辑的。而对于有符号数据(默认的声明的整型对象),算术的或者逻辑的右移都可以。不幸的是,这就意味着任何假设一种或者另一种右移形式的代码都潜在着可移植性问题。然而,实际上,几乎所有的编译器/机器组合都对有符号数据使用算术右移,且许多程序员也都假设机器会使用这种右移。
另一方面,Java对于如何进行右移有明确的定义。表达式x>>k会将x算术右移k个位置,而x>>>k会对x做逻辑右移。
当移动k位,这里k很大时,对于一个由w位组成的数据类型,如果要移动k≥w位会得到什么结果呢?例如,在一个32位机器上计算下面的表达式会得到什么结果:
Int lval = 0xFEDCBA98
int lval = 0xFEDCBA98 >> 36
unsigned lval = 0xFEDCBA98u >> 40;
C语言标准很小心地规避了说明在这种情况下该如何做。在许多机器上,当移动一个w位的值时,移位指令只考虑位移量的低log2w位,因此实际上位移量就是通过计算k mod w得到的。例如,在一台采用这个规则的32位机器上,上面三个移位运算分别是移动0、4和8位,得到结果:
Lval 0xFEDCBA98
Aval 0xFEDCBA9
Uval 0x00FEDCBA
不过这种行为对于C程序来说是没有保证的,所以移位数量应该保持小于字长。另一方面,Java特别要求位移数量应该按照我们前面所讲的求模的方法来计算。
与移位运算有关的操作符优先级问题 常常有人会写这样的表达式1
C语言的排序法:
#include<stdio.h>
int main()
{
int i,t,j;
int score[10]={52,90,67,77,68,93,88,74,66,87};
printf("排序前:n");
for(i=0;i<10;i++)
printf("%dn",score[i]);
t=score[0];
for(i=0;i<10;i++)
for(j=i+1;j<10;j++)
if(score[i]>score[j])
{
t=score[i];
score[i]=score[j];
score[j]=t;
}
printf("排序后:n");
for(i=0;i<10;i++)
printf("%dn",score[i]);
return 0;
}
如果想更深入了解for里面的数值变化,不妨使用下调试功能。
文章来源:森动网小鱼儿,转载请注明出处!
更多资源:http://www.sendong.com/