003-变量,运算符,位运算
变量赋值,作用域,生命周期
利用"="来进行赋值,右值赋给左值,等号左值不能是常量
"=“和”=="可能会混淆,因为某些原因漏写
例子:
if(a = b) 错误写法!!!
{
执行语句、、、
}
if(-1 == a)
{
执行语句、、、
}
当判断双方有一方为常量时,可把常量写在等号左边;
问题:
int a = ‘a’; //对吗? 对,编译器允许这么写
因为ASCII码值得存在
printf(“%c\n”,97); //对吗? 对,打印a;
变量的生命周期与作用域?
**生命周期:**当一个变量被系统分配存储空间是开始,直到该变量的空间被释放为止
**作用域:**目标变量能被访问的区域;
从变量定义的位置开始,直到区域结束;
对于局部变量而言,定义位置开始,到局部区域结束,区域指的是花括号({})囊括的区域;
对局全局变量而言,从定义位置开始,到整个c文件的结束。
注:定义变量时,同一作用域内,不能出现同名变量。
局部变量&全局变量
局部变量定义在函数内的变量叫局部变量;
全局变量定义在函数外的变量叫全局变量;
定义:
局部变量:
局部变量的生命周期从定义被执行时开始,到函数结束被释放;
被存放在栈区;
局部变量被定义时,若未被初始化,则局部变量也可以被直接访问;
但是因为系统未对分配空间进行清零,所以局部变量的具体值不确定。
全局变量:
全局变量的生命周期从函数启动开始就被分配了,到程序结束;
未被初始化的全局变量被存放在bss段;
被初始化的全局变量被存放在data段;
全局变量被定义时,若未被指定初始化,则系统会默认初始化为0。
如图所示:
精度:
计算时,默认由低精度向高精度转换,保证精度的不丢失;
当强制把高精度转换成低精度数据时,会丢失精度;
运算符:
=
利用"="来进行赋值,右值赋给左值,等号左值不能是常量
赋值运算时需要注意等号左右的类型匹配问题
+ - *
/
当除数与被除数均为整数时,结果一定为整数
且遵循只保留整数部分的规则,即是小数部分会被直接舍去,而不会进行四舍五入
例子:
int a = 5;
a/2的结果是? 2 当除数与被除数中任一数字为小数时,则结果为小数
例子:
int a = 5;
a/2.0的结果是? 2.5
% 取余(取模)
取余时,除数与被除数都需要为整数
例子:
int a = 1234; 取出a各个位置的数字
个位:a/1%10 = 4 a%10/1=4
十位:a/10%10=3 a%100/10=3
百位:a/100%10=2 a%1000/100=2
千位:a/1000%10=1 a%10000/1000=1
++ -- 自加/自减
i++/++i 相当于i=i+1;
i--/--i 相当于i=i-1;
例子:
int i = 1; int a = i++; //执行完i=2
int b = ++i;
int d = (a++)+(++b);
a和b的值是?
a=1,b=3
d的值是?
5 前置 ++i/–i
先加减,后运算
后置 i++/i–
先运算,后加减
+= -= *= /= 赋值运算()
把右值赋值给左值,左值一定是变量
运算过程是左值本身与右值进行对应运算,把运算结果再赋值给左值
例子:
int i = 3; i+=2; //等价于i = i+2
i的值是?
5例子:
int i = 3;
int a = 1;表达式i += a++执行3遍后 a和i的值是? 4 9 即是把i = i+a++循环3遍 次数 运算后i 运算前i 运算前a 运算后a 1 4 3 1 2 2 6 4 2 3 3 9 6 3 4
int i = 3;
int a = 1;
表达式i += ++a执行3遍后
a和i的值是?
4 9 即是把i = i+(++a)循环3遍
次数 运算后i 运算前i 运算前a 运算后a
1 5 3 2 2
2 8 5 3 3
3 12 8 4 4
真/假 true/flase 真也叫非假,假也叫做非真
什么数字能表示真?
非0
什么数字能表示假?
0
真和假若参与运算,可以吗?
可以
真和假会被当成什么数字来参与运算?
假转换为0
真转换为1
> < >= <= == != 关系运算符,大小比较
一般作为判断条件,或者循环条件
例子:
if(1 > 2) //恒为假
{
… 永远不可能执行
} if(1 < 2) //恒为真 也可以写为if(1)
{
}
&& || ! 复合逻辑运算符
格式:
if(表达式1 && 表达式2 && 表达式3 && ...)
{
执行语句1。。。
执行语句2。。。
}
当所有表示均分别为真时,则对应的复合表达式结果为真
若其一为假,则表达式结果为假
if(表达式1 || 表达式2 || 表达式3 || ...)
{
执行语句1。。。
执行语句2。。。
}
若其一为真,则表达式结果为真
例子:
int a=1,b=2,c=3,d=4; if(a>b && b>c || c<d)
{
…
}
判断式的结果真假?
真
int a=0,b=1,c=2,c=3;
if(a++ && b++ && c++ && d++)
{
…
}
判断式的结果真假?
假
请问a、b、c、d分别等于多少?
0、1、2、3
int a=0,b=1,c=2,d=3;
if(d++ && c++ && b++ && a++)
{
…
}
判断式的结果真假?
假
int a=0,b=1,c=2,c=3;
if(a++ || b++ || c++ || d++)
{
…
}
判断式的结果真假?
真
总结:符合表达式中,按照从左向右的顺序逐个进行真假判别
当某一个表达式分支的真假能决定整个表达式的真假时
则判断运算到此结束,判断表达式中所牵扯的运算将不在执行
! 非,意义是真变假,假变真
位运算 针对的是二进制
& 位与
把目标值转换为对应的二进制,然后对应位与对应位进行与运算
与运算的规则是若两个数值的对应位有一个为0,则结果的对应位为0
有0为0
例子:
66&22
0100 0010
& 0001 0110
-------------
0000 0010
| 位或
把目标值转换为对应的二进制,然后对应位与对应位进行或运算
或运算的规则是若两个数值的对应位有一个为1,则结果的对应位为1
有1为1
例子:
66|22
0100 0010
| 0001 0110
-------------
0101 0110
^ 异或
把目标值转换为对应的二进制,然后对应位与对应位进行异或运算
异或运算的规则是若两个数值的对应位相同,则结果的对应位为0
若不同,则结果的对应为1
例子:
66^22
0100 0010
^ 0001 0110
-------------
0101 0100
思考:
一个数字和0进行异或运算,结果是??
是该数字本身
一个数字和自己进行异或运算,结果是??
0
例子:
int a = 66;
int b = 22;
编写程序交换a和b的值
a = a^b; //a = 66^22;
b = a^b; //b = 66^22^22 = 66;
a = a^b; //a = 66^22^66 = 22;
~ 取反
把目标值转换为对应的二进制,然后对应位进行运算
对应位为0,则结果的对应位为1
对应位为1,则结果的对应位位0
注意取反时,符号位不变
数字本身在进行存储时,存储的是数字的补码
数字有原码,反码,补码
正数的原码,反码,补码与原码是一致的
负数的源码取反获得反码
负数的反码+1获得补码
正数和负数区别: 针对的是有符号数
正数的最高位为0
负数的最高位为1
有符号数与无符号数的区别最高为是否作为符号位
signed int a; 有符号数a
unsigned int b; 无符号数b
1111 ... 1111 ~ 0111 ... 1111
------32----- ------32-----
a的取值范围是-(2^31-1) ~ 2^31-1
0000 ... 0000 ~ 1111 ... 1111
------32----- ------32-----
b的取值范围是0 ~ 2^32-1
思考:
+0或-0
+0
原码 0000 ... 0000
反码 0000 ... 0000
补码 0000 ... 0000
-0
原码 1000 ... 0000
反码 1111 ... 1111 取反
补码 10000 ... 0000 +1
超出数据位的被舍弃
<< 左移
向高位移动
>> 右移
向低位移动
注意:
负数的算术右移,补1
例子:
123 0111 1011
把123的第7位置为1,且不改变其它位的数据
目标结果 1111 1011
-------------
| 0111 1011
1*** *0**
1000 0000 参与计算的数字
1<<7
最终计算式:
123 | (1<<7)
把123的第6位置为0,且不改变其它位的数据
目标结果 0011 1011
-------------
& 0111 1011
*011 1*11
1011 1111
0100 0000
1<<6
最终计算式:
123 & ~(1<<6)
提示:
<< ~ 1 | &
注释的方式方法:
注释内容不会被编译进文件;
1.行注释
在"//"后面跟上注释内容
2.块注释
在注释区域之前的位置添加"/*"
在注释区域之后的位置添加"*/"