表示离散值的两种方法:一种是用位表示离散值,还有一种是把离散值作为有限集中的元素。
容易忘记的知识点:
1、补码
非负整数n的补码表示形式就是n的二进制位字符串。如果我们对位字符串进行按位求反,并把结果加上1,我们就得到了-n的补码、
2、左移位和右移位
移位操作符的左右两个操作数都必须是整型表达式,每个操作数都会执行类型的提升。整个表达式的类型就是经过提升后的左操作符的类型。
例如:char c = 'z';
当进行c << 1移位的时候,它被提升为int型,当移位表达式进行求值的时候,两个操作数分别会执行整型提升,整个表达式的类型就是经过提升后的做操作符的类型。因此像c<<1这样的表达式的值是按照4个字节存储的。
3、移位操作符的优先级和结合型
a<< b >> 1 等价于 (a << b) >> 1
a << 1 + 2 << 3 等价于 (a<<(1+2)) << 3
a + b << 12 * a >> b 等价于((a+b)<<(12*a))>>b
4、掩码
掩码是一个常量或者是变量,用于从另一个变量或表达式提取所需要的位,由于int常量1的二进制表达式入下:00000000 00000000 00000000 00000001
它可以用于确定一个int表达式的低端位,下面的代码使用了这个掩码,打印出一个0和1交替的序列。如果想找到一个数字的某个位置上的数字,那么把掩码的该位置为1进行与操作就可以得到。
例子:
void bit_print(int a)
{
int i;
int n = sizeof(int )*CHAR_BIT; // int limit.h
int mask = 1<<(n-1);
for(i = 1;i <= n; ++i)
{
putchar(((a & mask) == 0)? '0':'1');
a<<=1;
if(i%CHAR_BIT == 0 && i < n)
putchar(' ' );
}
}
例子解读:上面的例子功能是输出一个整数的二进制数:其中 int mask = 1 << (n-1); 这条语句是把1进行移位,移到该二进制位数的最高位。putchar(((a&mask) == 0)? ‘0’:‘1’); 这条语句,是把每一个输入的数字与mask进行与运算,对每个数字的最高位与运算之后输出最高位的二进制。 之后a<<1把a向左移位,改变最高位,进行下一次循环的输出。
5、包装和解包
使用位表达式可以根据字节对边界数据进行压缩。这不仅有利于节省空间,更重要的是有助于节省时间。在一台字长4字节的机器上,每个指令周期并行处理32位。下面这个函数可以把4个字符包装成一个int,使用移位操作进行基于字节的包装。
#include <limits.h>
int pack(char a,char b,char c,char d)
{
int p = a;
p = (p << CHAR_BIT) | b;
p = (p << CHAR_BIT) | c;
p = (p << CHAR_BIT) | d;
return p;
}
程序解读:上面程序打包a,b,c,d成为p并利用打印函数,打印结果。
解包:#include <limits.h>
char unpack(int p,int k)
{
int n = k * CHAR_BIT;
unsigned mask = 255;
mask << n;
return ((p & mask) >> n);
}