C语言基础-操作符和表达式
5.1 操作符
操作符分为:
- 算数操作符(除%只适合整数,其他既适合整数也适合浮点数):+ - * / %
- 移位操作符(两个操作数都必须是整数):>> <<
注意:严禁这种写法sa << -5;不能为负数。 - 位操作符(操作数为整数):& | ^ ~
- a.把指定位置1 :
value |= 1 << (which_bit - 1); - b.把指定位置0 :
value &= ~(1 << (which_bit - 1)); - c.测试指定位是否为1:
re = value & 1 << (which_bit - 1);
- a.把指定位置1 :
- 赋值操作符: =
- 赋值也是一个表达式,是表达式就具有一个值,该值为左操作数的新值。
- 赋值操作符的结合性(求值顺序)是从右到左。
例:a = x = y + 5;相当于a = ( x = y + 5 );
注意:上式中,如果x为字符类型,a为短整型。那么y+5的值会被截去一段后赋值给x,但是x会扩展为整形再给a。所以getchar()函数返回一个整形值而不是字符值。
| 复合赋值符 | += | -= | *= | /= | %= | <<= | >>= | &= | ^= | |= |
|---|
/*
**计算二进制数含有1的位数
*/
int cnt_1bits( unsigned value)
{
int ones;
for( ones = 0; value != 0; value >>= 1) if( (value & 1) != 0 ) ones += 1;
return ones;
}
- 单目操作符: ! ++ -- - + ~ & * sizeof (类型)
- ‘&’用来产生它的操作数的地址。如:
int a, *b; b = &a; - '*'间接访问操作符,与指针一起使用。
- sizeof 操作符判断他的操作数类型的长度,以字节单位表示。
sizeof( int ); sizeof( x );括号在表达式中总是合法的,
在判断表达式长度时不会对表达式进行求值。如:sizeof( a = b + 1 );并未对a赋值。 - 强制转换(cast),显示的转换表达式的值为其他类型。如:
int a; (float) a;
- ‘&’用来产生它的操作数的地址。如:
- 关系操作符:> < >= <= != ==
符合表达式条件,则表达式的值为1,反之为0。C语言没有布尔值,用整型值;0是假,非0是真。。 - 逻辑操作符:&& ||
逻辑操作符会对两个表达式的施加控制,成为短路求值”short-ciruited evaluation“。 - 条件操作符:? : 如:
re = expression1 ? expression2 : expression3; - 逗号操作符: ,
逗号操作符将两个或者多个表达式分割开来,这些表达式从左到右依次求值,整个逗号表达式的值就是最后一个表达式的值。
a = get_value();
count_value( a );
while( a > 0 ){
...
...
a = get_value();
count_value( a );
}
上面代码块可以用下面简捷写法:
while( a = get_value(), count_value( a ), a > 0){
...
}
- 下标引用 [], 函数调用, 结构成员 .或者->
- 下标引用:
array[x]可以写成:*( array + x) - 结构成员:如果s是一个结构体变量,则s.a访问s中名为a的成员。如果p是指向结构的指针,那么用p->a访问成员。
- 下标引用:
5.2 左值和右值
- 左值就是可以出现在赋值符号左边(标识了一个特定的内存位置)
- 右值就是可以出现在赋值符号的右边(地址或者存储在某个位置的值)
- 左值可以出现在赋值符号右边但是右值不能出现在左边。
5.3 表达式求值
操作符的优先级:
lexp标识左值表达式;L-R表示从左到右依次求值。
| 操作符 | 描述 | 用法示例 | 结果类型 | 结合性 | 是否控求值顺序 |
|---|---|---|---|---|---|
| () | 聚组 | (表达式) | 同表达式 | N/A | N |
| () | 函数调用 | rexp(rexp1,……,rexpn) | rexp | L-R | N |
| [] | 下标引用 | rexp[rexp1] | lexp | L-R | N |
| . | 访问结构成员 | lexp.name | lexp | L-R | N |
| -> | 访问结构指针成员 | rexp->name | lexp | L-R | N |
| ++ | 后缀自增 | lexp++ | rexp | L-R | N |
| -- | 后缀自减 | lexp++ | rexp | L-R | N |
| ! | 逻辑反 | !rexp | rexp | R-L | N |
| ~ | 按位取反 | ~rexp | rexp | R-L | N |
| + | 单目,正值 | +rexp | rexp | R-L | N |
| - | 单目,负值 | -rexp | rexp | R-L | N |
| ++ | 前缀自增 | ++lexp | rexp | R-L | N |
| -- | 前缀自减 | --lexp | rexp | R-L | N |
| * | 间接访问 | *rexp | rexp | R-L | N |
| & | 取地址 | &lexp | lexp | R-L | N |
| sizeof | 求字节长度 | sizeof( 类型 || rexp ) | rexp | R-L | N |
| (类型) | 强制转换 | (类型) rexp | rexp | R-L | N |
| * | Mul | rexp | L-R | N | |
| / | div | rexp | L-R | N | |
| % | 取余 | rexp | L-R | N | |
| + | add | rexp | L-R | N | |
| - | sub | rexp | L-R | N | |
| << | sl | rexp | L-R | N | |
| >> | sr | rexp | L-R | N | |
| > | g | rexp | L-R | N | |
| >= | geq | rexp | L-R | N | |
| < | l | rexp | L-R | N | |
| <= | leq | rexp | L-R | N | |
| == | eq | rexp | L-R | N | |
| != | neq | rexp | L-R | N | |
| & | 与 | rexp | L-R | N | |
| ^ | 异或 | rexp | L-R | N | |
| | | 或 | rexp | L-R | N | |
| && | 逻辑与 | rexp | L-R | Y | |
| || | 逻辑或 | rexp | L-R | Y | |
| ?: | 条件操作符 | rexp | N/A | Y | |
| = | 赋值 | rexp | R-L | N | |
| += | rexp | R-L | N | ||
| -= | rexp | R-L | N | ||
| *= | rexp | R-L | N | ||
| /= | rexp | R-L | N | ||
| %= | rexp | R-L | N | ||
| <<= | rexp | R-L | N | ||
| >>= | rexp | R-L | N | ||
| &= | rexp | R-L | N | ||
| ^= | rexp | R-L | N | ||
| |= | rexp | R-L | N | ||
| , | 逗号操作符 | rexp | L-R | Y |
表达式的求值顺序是由3个因素决定的: 操作符的优先级,操作符的结合性,操作符是否控制执行的顺序。
两个相邻的操作符哪个先执行取决于它们的优先级,如果两者的优先级相同则尤其结合性决定。
隐式转换和算术转换:
- 隐式转换:C语言的整型算术数运算总是至少以缺省整形类型的精度来计算的,如果表达式中有字符类型和短整型,在使用之前都被转化为普通整型(integral promotion)。
- 算术转化:操作符的各个操作数必须要属于同一种类型。
| 算术转化”优先级“ |
|---|
| Long double |
| double |
| float |
| unsigned long int |
| long int |
| unsigned int |
| int |
浙公网安备 33010602011771号