【C入门】程序中的运算

Summary

1)C语言中支持如下4种类型的运算:

运算类型 运算符
四则运算 +,-,*,/,%
关系运算 <,>,<=,>=,==,!=
逻辑运算 &&,!,II
位运算 &,I,^,>>,<<,~

2)运算符的优先级:单算移比,按逻三赋。如果不同类型的运算符同时出现在一个表达式中,尽量用括号()指明运算顺序。

3)逻辑运算的短路法则:对于&&运算,第一个为假的操作数之后的其他操作数都不再计算;对于||运算,第一个为真的操作数之后的其他操作数都不再计算。因此对于if表达式的逻辑表达式,一定要考虑到后续的操作数是否需要运算到。

4)十进制负数和二进制的相互转换规则如下:

  • 1)符号位
  • 2)绝对值(二进制)
  • 3)按位取反
  • 4)加1
    如果一个二进制位表示的是一个负数,那么推算的方式按上述规则逐步相反。

5)在计算机中,不同数据类型的本质在于:

  • a)占用的内存大小不同:如int占4字节,char占1字节
  • b)表示数据的具体方式不同:如正整数用原码表示、负整数用补码表示;整数和浮点数的二进制表示方法不同。

6)位运算操作时的关键点:

  • a)操作数的类型(占用的内存大小)
  • b)符号位(0还是1)
  • c)不同数据类型的运算要先对齐,再运算(补符号位进行对齐

7)设置整数integer指定Bit位的值
规则如下:

  • 置0:使用按位与(运算数n指定位置为0,其余为1,同integer进行&运算),如果对应位置为0,其余位置可以不变为1,这样运算数n能小一点,直观一些
  • 置1:使用按位或(运算数n指定位置为1,其余为0,同interger进行|运算)
  • 取反按位异或(如一次指定多位取反)

1、四则运算

四则运算(+, -, *, /, %)

  • 就是数学中的加减乘除等运算
  • 遵循先乘除后加减的运算优先级
  • 可以使用括号改变运算顺序

注意:
C语言中的除法运算,除数不能为0
/和%都是除法。对于“/”,运算的结果和大类型一致。对于“%”,只能作用于整型数

int a = 1;
int b = 2;
int c = 0;

c = a / b;     // 计算得到除法的商,大类型为int,结果仍然是int
prinf(\"c = %d\\n\", c);     // c = 0

c = a % b;    // 计算得到出发的余数,只能作用于整型数
prinf(\"c = %d\\n\", c);     // c = 1

double a = 5;
double b = 2;
double c = 3;

c = a / b;    // 两个浮点数的除法,大类型为double,结果仍然是浮点数double
prinf(\"c = %f\\n\", c);     // c = 2.5

c = a % n;    // error,取余运算不可以作用于浮点型

2、关系运算

关系运算(<, >, <=, >=, ==, !=)

  • 比较两个值大小关系或相等关系的运算
  • 比较的结果为逻辑值:真(1)、假(0)
  • 可以使用括号()改变关系运算的顺序

int a = 1;
int b = 2;
int c = 0;

// 对于多个运算符杂糅在一个表达式中,运算符优先级见summary 2)
c = a - b >= a + b;        // 等价于:c = (a - b) >= (a + b);
prinf(\"c = %d\\n\", c);     // c = 0

c = a < b + c < b;        // 等价于: c = (a < (b + c)) < b;
prinf(\"c = %d\\n\", c);     // c = 1

3、逻辑运算

逻辑运算(&&, ||, !)

  • 逻辑运算的参与者为逻辑值(真或假)
  • 任何非零值在逻辑运算中都为真
  • 任何零值在逻辑运算中都为假

对于&&运算:运算数全1得1,否则为0;
对于||运算:运算数有1得1,全0为0;
对于!运算:单目运算符(只需要一个操作数),运算结果为;逻辑值;对真值取非的结果为假,对假值取非的结果为真;

  • C语言中的真值对应于非零值,假值对应于零值。如:1、1.6、-1、-0.8均为真值;如0、0.0、-0等都是假值。

逻辑运算中的短路法则
对于&&运算

  • 从左向右进行,如果有一个操作数为假,则整个表达式为假
  • 第一个为假的操作数之后的其他操作数不再计算

对于||运算

  • 从左向右进行,如果有一个操作数为真,则整个表达式为真
  • 第一个为真的操作数之后的其他操作数不再计算

4、位运算

位运算(&, |, ~, ^, <<, >>)

  • 直接对数据的二进制位进行操作
  • 位运算的基本单位是二进制位,所以也是一种0和1的操作
  • 可以使用括号()改变位运算的运算顺序
  • 位运算的操作数只能是整型数(浮点数不能进行位运算)
运算符 含义 示例 优先级
~ 按位求反 ~0101 -> 1010 1(高)
<< 左移:高位移出,低位补0 0011 << 1 -> 0110 2
>> 右移:低位移除,高位补符号位 0101 >> 2 -> 0001 2
& 按位与 0111 & 1100 -> 0100 3
^ 按位异或:相同为0,不同为1 0111 & 1100 -> 1011 4
I 按位或 0111 & 1100 -> 1111 5(低)

运算符优先级:
【C入门】程序中的运算

4.0 位运算操作时的关键点

在计算机中,不同数据类型的本质在于:
1)占用的内存大小不同:如int占4字节,char占1字节
2)表示数据的具体方式不同:如正整数用原码表示、负整数用补码表示;整数和浮点数的二进制表示方法不同。

位运算操作时的关键点

  • a)操作数的类型(占用的内存大小)
  • b)符号位(0还是1)
  • c)不同数据类型的运算要先对齐,再运算(补符号位进行对齐
short a = 1;    // 0001
short b = 2;    // 0010
int X = a - b;    // a - b = -1 short;由于-1在int能表示的范围内,所以隐式转换不会出问题
                // 从二进制层面来说,short类型的-1转换到int类型的-1,需要在高位补符号位,
                // 即要补高16位的1,二进制值为11...11,十进制为-1
printf(\"X = %d\\n\", X);    // X = -1;

X = X >> 4;        // -1 >> 4,低位舍弃,高位补符号位,仍然是11...11,-1
printf(\"X = %d\\n\", X);    // X = -1;

X = X * -1 * 16 >> 4;   // 单 算 移 比 按 逻 三 赋
                        // -1*-1*16 = 16; 16 >> 4,右边移动,高位,补符号位,所以是00...0001,1
printf(\"X = %d\\n\", X);    // X = 1;

// 对于一个正整数,右移n位,X >> n,相当于除以2^n;左移n位,相当于乘以2^n
// 数据符号位的具体位置由数据类型决定的,如char,最高位是第7位;int,最高位是第31位

4.1 负数的二进制表示方法

十进制负数和二进制的相互转换规则如下:
1)符号位
2)绝对值(二进制)
3)按位取反
4)加1
示例如下(以1字节为例):

// 十进制数-128的二进制表示:1000 0000
1)符号位:1
2)绝对值(二进制):1000 0000
3)按位取反:0111 1111
4)加1:1000 0000 (补码)
// 另,-128,-32768等这几个负数比较特殊,在计算机中没有原码和反码,只有补码来表示,二进制位等价于-0。


// 十进制数-10的二进制表示:1111 0110
1)符号位:1
2)绝对值(二进制):0000 1010
3)按位取反:1111 0101
4)加1:1111 0110(补码)

// 如果一个二进制位表示的是一个十进制整数,通过符号位得知是个负数,则可以按相反的运算方式进行推算。
// 二进制1111 0110到十进制数的转换:-10
4)减1:1111 0101
3)按位取反:0000 1010
2)绝对值(十进制):10
1)加上符号位:-10

4.2 设置整数integer指定Bit位的值

规则如下:

  • 置0:使用按位与(运算数n指定位置为0,其余为1,同integer进行&运算),如果对应位置为0,其余位置可以不变为1,这样运算数n能小一点,直观一些
  • 置1:使用按位或(运算数n指定位置为1,其余为0,同interger进行|运算)
  • 取反按位异或(如一次指定多位取反)

示例如下:


// eg.1 设置整数5的第2个二进制位为1

使用按位或方式:运算数n为 0000 0010 = 2,整数5为 0000 0101
    0000 0010     2
|   0000 0101     5
    0000 0111 ==  7
    
    
// eg.2 设置整数15的第2个二进制位为0

使用按位与方式:运算数n为 0000 1101 = 2,整数15为 0000 1111
    0000 1101     13
&   0000 1111     15
    0000 1101 ==  13
    
// eg.3 设置整数a的中间4位取反,a = 0x10101101,运算数n应为多少?

使用按位异或方式:运算数n为 0000 0010 = 2,整数a为 1010 1101
    0011 1100     n,60
^   1010 1101     a,-83
    1001 0001 ==  X,-111

本文总结自“狄泰软件学院”唐佐林老师《C语言入门课程》。
如有错漏之处,恳请指正。

【C入门】程序中的运算

上一篇:redis 持久化


下一篇:红黑树