本博文为C语言_运算符1的继续,因此其编号顺序继承自原博文
位移运算符包括左移动<<
运算符 和 右移>>
运算符
<<
左移运算符<<
将其左侧运算对象每一位的值向左移动其右侧运算对象指定的位数。左侧运算对象移出左末端位的值丢失,用0填充空出的位置。
如:
(10001010)<< 2 //表达式
00101000 //结果值
该操作产生新的位值,但不改变原来运算对象的值
如:
int stonk=138;//stonk=10001010
int moveVal=2;
int newStonk = stonk<<moveVal;
printf("stonk=%d\nnewStonk=%d\n",stonk,newStonk);
>>
右移运算符>>
将其左侧运算对象每一位的值向右移动其右侧运算对象指定的位数。左侧运算对象移出右末端位的值丢失。
对于无符号类型,用0填充空出的位置;
对于有符号类型,其结果取决于机器,空出的位置可以用0填充,或者用符号位的副本填充
无符号类型实例:
(10001010)>>2 //表达式,无符号值
00100010 //所有系统都得到该值
有符号型实例:
(10001010) >> 2 //表达式 有符号值
00100010 //某些系统上的结果
同样的1000101/
(10001010)>> 2 //表达式值,有符号
11100010 //在另一些系统上的结果值
注意:
右移运算符在对有符号型数进行运算过程中,会因为机器型号问题,产生计算结果的差别
使用位移运算符进行乘除法运算要比普通的乘除法运算符*、/
运算效率更高
乘法运算:
unsigned int val=150;//val=1010110
int n=2;
unsigned int newVal= val << 2;
printf("val=%d\nnewVal=%d",val,newVal);
除法运算
unsigned int val=133;//val=10100101
int n=2;
unsigned int newVal= val >> 2;
printf("val=%d\nnewVal=%d",val,newVal);
由于基于位移运算符的乘除法,其底层是移动位,所以其乘除法运算是对2的幂进行乘除
假设用一个unsigned long类型的值表示颜色值,低阶位字节存储红色的强度,下一个字节存储绿色强度,第3个字节存储蓝色强度。
那么,如何将每种颜色的强度分别存储在3个不同的unsigned char 类型的变量中
编程思路:
用有移运算符将8位颜色值移动到低阶字节,然后用掩码技术将低阶字节赋值给指定变量
#include
using namespace std;
#define BYTE_MASK 0xff
int main()
{
unsigned long color = 0x002a162f;
unsigned char blue, green, red;
red = color&BYTE_MASK;
green = (color >> 8)&BYTE_MASK;
blue = (color >> 16)&BYTE_MASK;
printf("red=%x\n", red);
printf("green=%x\n", green);
printf("blue=%x\n", blue);
cin.get();
return 0;
}
将十进制数字转换为二进制,要求使用位移运算符符解决问题
解题思路
- 从接盘输入值进行读取十进制数,以任意的非数字结束程序
- 十进制转换为二进制思路是用掩码获取输入值的最后一位,然后将获得的最末尾值存入数组,
由于本例中定义数组为字符型,所以需要在存入数组前将其+‘0’完成字符值的‘1’ 和‘0’转换- 为便于阅读,将结果以四位四位的形式输出
代码:
#include
#include //supply the define of CHAR_BIT, CHAR_BIT means how many bits in one byte
char* itobs(int, char*);
void show_bstr(const char*);
int main()
{
char bin_str[CHAR_BIT * sizeof(int) + 1];
int number;
puts("Enter integers and see them in binary");
puts("Non-numeric input terninates program");
while (scanf("%d", &number) == 1)
{
itobs(number, bin_str);
printf("%d is", number);
show_bstr(bin_str);
putchar('\n');
}
getchar();
return 0;
}
char* itobs(int n, char* ps)
{
int i;
const static int size = CHAR_BIT * sizeof(int);
for (i = size - 1; i >= 0; --i)
{
ps[i] = (01 & n) + '0';
ps[size] = '\0';
n >>= 1;
}
return ps;
}
void show_bstr(const char* str)
{
int i = 0;
while (str[i])
{
putchar(str[i]);
if (++i % 4 == 0 && str[i])
{
putchar(' ');
}
}
}
关键点说明:
CHAR_BIT* sizeof(int)
表示int类型的位数,+1表示数组需要给数组末尾留空字符位置请写一个函数用于切换一个值中的后n位, 要求:待处理值和n都是函数的参数
解题思路:
首先创造一个满足n位需求的掩码
其次使用^
运算符进行求解
int invert_end(int num, int bits)
{
int mask = 0;
int bitVal = 1;
while (bits > 0)
{
mask |= bitVal;
bitVal <<= 1;
bits--;
}
return num^mask;
}
代码解释:
while循环用来创造所需要的掩码,最后num^mask运算获得结果
操作位的第二种方法为位字段(bit field)
位字段是一个signed int 或 unsigned int类型变量中的一组相邻的位
位字段通过一个结构声明来建立,该结构声明为每个字段提供标签,并确定该字段的宽度。
创建两个1位的字段,一个2位的字段和一个8位的字段
struct
{
unsigned int code1 : 1;
unsigned int code2 : 1;
unsigned int code3 : 2;
unsigned int code4 : 8;
}prcode;
给位字段赋值的方式为:
prcode.code1=1;
prcode.code3=3;
prcode.code4=20;
注意:
发生跨越时,会产生未命名的“洞”,解决这个问题的方法是定义一个未命名的字段来填充洞
以下代码用来解决字段跨越问题:
struct
{
unsigned int field1 : 1;
unsigned int : 2;//解决字段1的跨越问题
unsigned int field2 : 1;
unsigned int field3 : 8;
}stuff;
位字段和位运算是两种可以互相替代的方式,因此此处不在论述,详细请参见《C primer plus》P1161
带书签课本资源请联系[email protected] 费用1元/次