操作符和表达式
在笔记4中,介绍了C语言的基本循环语句.本节将介绍C语言中 变量五花八门的操作.
操作符:
分成了算数操作符、移位操作符、位操作符、赋值操作符、单目操作符、关系操作符、逻辑操作符、条件操作符、逗号操作符等等....
算数操作符: 包括 + - * / %
注意: 5/2 =2 , 整数相除,直接舍掉小数部分,不会进行四舍五入。
% 取模运算,只接受整数之间的取模。
整数和浮点数进行 + - * / 结果,结果是浮点数,还要看赋值运算符左边变量的类型.
移位操作符 : << 和 >>
左操作数的将进行移位,移动位数 n=右操作数值。方向为向左或向右。 如 011 <<3 , 将会 011000
其实左移右移都是分:逻辑移位和算数移位的.
但在底层硬件中: 逻辑左移和算数左移都是执行高位舍弃,地位补0的操作。使得逻辑左移和算数左移结果一直保持一致。
(汇编码SAL 指令同 SHL,是同一条指令的两种助记符,执行的同一操作)
但在底层硬件中: 逻辑右移和算数右移是不一样的, 逻辑右移: 高位补0,地位舍弃. 算数右移: 高位补符号位,地位舍弃.
(汇编SAR 与 SHR 不同,SHR左边高位补0,而 SAR 补的不是0,而是原来的符号位。)
C语言标准对 "无符号数"的左右移位,做了明确的规定 : 无符号数的左右移位均是逻辑移位。
但对"有符号数"的左右移位,没有明确规定,导致各个编译器可能会有差别.
故: C语言中出现 符号数右移的,是不能可靠移植的. 故我们见到的>> ,都需要先声明 unsigned
还有一个问题: 因为编译器不一定支持 算数右移,那当我们想用算数右移的时候, 怎么写?
答案是: 需要我们用简单的代码去实现. 比如判断正负数然后执行不同的,,,
假如右侧移位值n是一个负数, 该怎么移位? 这些情况,C标准中都没有说,具体就得看编译器怎么实现的了,所以尽量避免这种
情况, 属于不可移植的代码.
位操作符: & | ^
这里没有将 ~ 放进来是因为 : & | ^需要两个操作数. ~ 是针对单个操作数.
主要用途是: 于移位寄存操作符配合,完成对一位的置1或清0操作。
rega | = (1 << n ) 把寄存器的第n位置1
rega &= ~(1 <<n) 把寄存器的第n位清0. 请不要质疑, 如8位寄存器, ~ (00100000) = 11011111
赋值操作符: =
在C语言中 a = x+3 ; 我们都能理解,把x+3的值,赋值给a.
其实 = 是个赋值操作符, a=x+3 是一个赋值表达式(注意不加;) ,表达式就有结果。
C语言规定赋值表达式的结果是左侧操作数的结果.
我们看这样一个程序:
#include <stdio.h>
int main(int argc,char **argv) { int a = 0; while(a=1) { printf("a=1 "); } }
我们想表达的意思是 如果 a = 1,就一直打印 "a=1", 但是误操作了 while(a==1) 错写成 while(a=1)
这里导致的结果就是: a=1 这个赋值表达式的结果是 a的新值1. 即while(1) ,陷入了死循环.如下图
从这个地方,我们也能反推,帮助理解赋值表达式是有结果的.
复合赋值符: 这个就是 a += 1 ;a |= 1 << 3,写法简单、易读。
单目操作符
单目操作符:有 ~ ! +- ++ -- & * sizeof (类型) 这几种
~: 安位取反。 有时候 ~(0x1) :其实得到的是 1111 1111 1111 1110
!: 是逻辑取反。 0x11得到的是 0.
± : 单纯的正负号,无特别的意义。
++、-- 操作: 它由分成前缀、和后缀两种。 如 a ++ ++a
int main (void)
{
int a, b,c,d ;
a = b = 10;
c = a ++ ;
d = ++b;
printf("ch=%d %d %d %d
",a,b,c,d);
}
从抽象的层次可以这样解读: ++a 和a++ 返回的结果均是一份拷贝值。
++a 是先执行 a=a+1操作后,再拷贝的a值,即新值
a++ 是先拷贝的a值,然后再执行a=a+1.故而可以看出这两个表达式返回值存在不同。
* & 更像是一对, &用于获取变量的物理地址信息; * point 用做右值时,表示会的 物理地址point的内容,用作左值时,表示存储位置。
sizeof () 括号内部可以是一个 数据类型名称、也可以使一个变量、或表达式。 用于获知所占字节数.
(类型) 是强制类型转换操作,在特别处理上还是有存在的必要的。比如除法操作.
关系操作符
主要包含 > >= < <= != == 一定注意 == 和 = 在 if()的本质区别。
逻辑操作符 && ||
跟位操作符有些类似,但 a && b 表示 条件a和条件b都为真, 整个表达式才为真。
a & b 则是 a的每一位 与b的对应位 做与运算.
BK2535 ATE测试的时候,有因为该问题导致过问题.
条件操作符
out = a ? 1 : 0 ; 三目表达式. 可以替代一些简单的if else表达式.
逗号操作符
expression1 , expression2 , ....expression m 这个表达式: 从左到右执行,并返回最终的结果----expression m的值.
因此在下面一种情况下常用:
fifo_empty = fifo_state & 0x01 ;
while(! fifo_empty) {
rdata = data_reg;
fifo_empty = fifo_state & 0x01 ;
}
为了读空fifo,则需要每次判断fifo_empty是否为空.
while( fifo_empty = fifo_state & 0x01 , ! fifo_empty )
rdata = data_reg;