知名网站开发企业,怎么做晒鱼的网站,大连在哪个省,网络品牌推广方案2.4 C语言之运算符 一、算术运算符二、关系运算符三、逻辑运算符四、自增自减运算符五、按位运算符六、赋值运算符七、条件表达式八、运算符优先级与求值次序 一、算术运算符
二元算术运算符包括#xff1a;(加)、-(减)、*(乘)、/(除)、%(取模)
整数除法会截断结果中的小数部… 2.4 C语言之运算符 一、算术运算符二、关系运算符三、逻辑运算符四、自增自减运算符五、按位运算符六、赋值运算符七、条件表达式八、运算符优先级与求值次序 一、算术运算符
二元算术运算符包括(加)、-(减)、*(乘)、/(除)、%(取模)
整数除法会截断结果中的小数部分表达式x % y的结果是x除以y的余数当x能被y整除时其值为0。取模运算符不能应用于float和double类型。在有负操作数的情况下整数除法截取的方向以及取模运算结果的符号取决于具体机器的实现这和处理上溢和下溢的情况是一样的二元运算符和-具有相同的优先级它们的优先级比*、/和%的优先级低而二元运算符*、/和%的优先级低于一元运算符和-算术运算符采用从左到右的结合规律
二、关系运算符
关系运算符包括、 、 、
关系运算符优先级相同关系运算符优先级低于算术优先级因此 i lim - 1 等价于 i (lim - 1)关系运算符优先级高于相等性运算符、!因此0 ! a 1 等价于 0 ! (a 1)
三、逻辑运算符
逻辑运算符包括与 、||或 、!非
由或||连接的表达式按从左到右的顺序进行求值并且在知道结果值为真或假后立即停止计算短路。优先级高于||但是两者都比关系运算符和相等性运算符的优先级低在关系表达式或逻辑表达式中如果关系为真则表达式的结果值为数值1如果为假则结果值为数值0逻辑运算符!的作用是将非0操作数转换为0将操作数0转换为1。一般这样用 if(!valid)一般不采用 if(valid0)
四、自增自减运算符
C语言提供了两个用于变量递增与递减的特殊运算符。自增运算符使其操作数递增1自减运算符--使其操作数递减1。
与--这两个运算符特殊的地方在于它们既可以用作前缀运算符n也可以用作后缀运算符n。在这两种情况下其效果都是将变量n的值加1。但是它们之间有一点不同。表达式n先将n的值递增1然后再使用变量n的值而表达式n则是先使用n的值然后再将n的值递增1。如果n的值为5那么 x n; 执行后的结果是将x置为5而 x n; 执行后的结果是将x置为6这两条语句执行完成后变量n的值都是6。自增自减运算符只能作用于变量类似于表达式(ij)是非法的
五、按位运算符
C语言提供了6个位操作运算符。这些运算符只能作用于整型操作数即只能作用于带符号或无符号char、short、int、long类型
运算符说明运算规则按位与AND参与运算的两个二进位都为1结果位才为1111, 100010000|按位或OR参与运算的两个二进位只要有一个为1结果位就为11|11 1|01 0|11, 0|00^按位异或XOR参与运算的两个二进位不同结果位为1相同结果位为01^10, 1^01, 0^11, 0^00左移mn将二进制位左移n位右移mn, 将二进制位右移n位~按位求反一元运算符0变1,1变0
按位与运算符经常用于屏蔽某些二进制位x1x; x00其中x取值0或者1比如 n n 0177; 该语句将n中除7个低二进制位外的其它各位均置为0 0177八进制–十进制127–二进制 01111111 可以看出0177对应的二进制的7个低位都是1那么不管n的7个低位是1还是0与0177进行运算之后这7位的结果总是保持不变而除了这7个低位n的其它位都将0其结果显然也是0按位或运算符|经常用于将某些二进制位置为1x|11; x0x其中x取值0或者1比如 n n | SET_ON; 该语句将n中对应于SET_ON中为1的那些二进制位置为1。按位异或运算符^当两个操作数的对应位不相同时将该位设置为1否则将该位设置为0注意区分按位运算符、| 与逻辑运算符、||比如 int x 1, y 2; printf(“%d”, x y); // 0 printf(“%d”, x y); // 1移位运算符和分别用于将运算的左操作数左移和右移移动的位数则由右操作数指定右操作数的值必须是非负值。表达式x2表示将x的值左移两位右边空出的两位用0填补该表达式等价于对左操作数乘以4在对unsigned类型的值右移时左边空出的部分用0填补在对signed类型的值右移时某些机器将对左边空出部分用符号位填补即算术移位而另一些机器则对左边空出部分用0填补即逻辑移位
#include stdio.hmain()
{int x 5; // 0000 0101 printf(%d\n, x 2); // 0001 0100 20x*4printf(%d\n, x 2); // 0000 0001 1x/4unsigned int y 5; // 0000 0101 printf(%d\n, y 2); // 0000 0001 1x/4signed int z -5; // 1000 0101原码 -- 1111 1010 反码原码取反 -- 1111 1011 补码反码加1printf(%d\n, z 2); // 1111 1011(-5补码) --右移2位左边空位补符号位 1111 1110补码 -- 1111 1101反码 -- 1000 0010原码 -2return 0;
}关于负数的二进制可以参考我的另一篇博客负数的二进制
一元运算符~用于求整数的二进制反码即1变0,0变1比如 int a 64 16 1;// 077八进制--十进制63--二进制 011 1111 --取反 0100 0000// 0101 0001 a//0100 0000 ~077//0100 0000a a ~077; // 将把a的最后六位设置为0printf(%d\n, a); 看一个例子 printf(%d\n, ~0); // -1 1000 0001 - 1111 1111(补)printf(%d\n, ~0 2); // 1111 1111(补) 2 -- 1111 1100(补) 1111 1011(反) 1000 0100(原) -4printf(%d\n, ~(~0 2)); // 1111 1100 --取反 0000 0011printf(%d\n, getbits(13, 2, 2));// 返回整数x从第p位从右边数假定最右边是第0位开始往右数n位的值也即除了这n位其左边位都置0
unsigned getbits(unsigned int x, int p, int n) {// 0000 1101 x13 p2 n2// 0000 0110 //0000 0011 // 0000 0010 2return (x (p 1 - n)) ~(~0 n);
}x (p 1 - n) 将要求的n位数移到最右端其中p1-n就是要求的n位数的右端的没用的位数 ~0所有位都为1 ~0n左移n位右端的n位置0 ~(~0n)右端的n位置1 做运算将n位左边位都置0
六、赋值运算符
在赋值表达式中如果表达式左边的变量重复出现在表达式的右边如 i i 2 则可以将这种表达式缩写为下列形式 i 2其中的属于赋值运算符 大多数二元运算符都有相应的赋值运算符op其中op可以是下面这些运算符之一 - * / ^ |
七、条件表达式
下面这组语句 if (a b)z a;elsez b;用于求a和b中的最大值并将结果保存到z中。条件表达式使用三元运算符 ? : 提供了另外一种方法编写这段程序及类似的代码段。在表达式 expr1 ? expr2 : expr3 中首先计算expr1如果其值不等于0为真则计算expr2的值并以该值作为条件表达式的值否则计算expr3的值并以该值作为条件表达式的值。expr2和expr3中只能有一个表达式被计算。因此以上语句可以改写为 z (ab) ? a : b; /* z max(a,b) */
八、运算符优先级与求值次序
下表总结了所有运算符的优先级与结合性同一行中的各运算符具有相同的优先级各行间从上往下优先级逐行降低。
运算符结合性() [ ] - .从左至右! ~ – - * (type) sizeof从右至左* / %从左至右 -从左至右 从左至右 从左至右 !从左至右从左至右^从左至右|从左至右从左至右||从左至右? :从左至右 - * / % ^ | 从右至左,从左至右
运算符- .用于访问结构成员sizeof 对象长度后续讨论一元运算符*(通过指针间接访问)一元运算符(对象地址)后续讨论注意一元运算符、-、*、优先级高于二元运算符、-、*、C语言没有指定同一运算符中多个操作数的计算顺序 || ?: ,运算符除外。例如 x f() g(); 在上面的语句中f()可以在g()之后计算也可以在g()之前计算。因此如果f或g改变了另一个函数所使用的变量那么x的结果可能会依赖这两个函数的计算顺序。解决办法是把中间结果保存在临时变量中。类似地C语言也没有指定函数各参数的求值顺序。例如 printf(“%d %d\n”, n, power(2, n)); 在不同的编译器中的输出结果可能不同这取决于先执行n的自增还是先执行power函数解决的办法是 n; printf(“%d %d\n”, n, power(2, n));函数调用、嵌套赋值语句、自增、自减都可能产生副作用在对表达式求值的同时修改了某些变量的值。在有副作用影响的表达式中其执行结果同表达式中的变量被修改的顺序之间存在着微妙的依赖关系比如 a[i] i; 数组下标i是引用旧值还是新值编译器不同结果可能不同。C语言标准对大多数这类问题有意未作具体规定。表达式何时会产生这种副作用对变量赋值将由编译器决定因为最佳的求值顺序同机器结构有很大关系。ANSI C标准明确规定了所有对参数的副作用都必须在函数调用之前生效但这对前面介绍的那种printf函数调用没有什么帮助在任何一种编程语言中如果代码的执行结果与求值顺序有关则都是不好的程序设计风格。如果不知道这些问题在各种机器上是如何解决的就不要尝试使用某种特殊的实现方式。