C语言基本数据类型
字符类型 char 1字节 [-128,127]
无符号字符类型 unsigned char 1字节 [0,255]
短整数类型 short 2字节 [-32768,32767]
unsigned short [0,65535]
short int
unsigned short int
整数类型 int 4字节 [-2^31,2^31 -1]
unsigned int [0,2^32 -1]
长整数类型 long int 4字节/8字节
long
unsigned long int
长长整数类型 long long int 8字节
单精度浮点类型 float 4字节 +-3.4*10^38
双精度浮点类型 double 8字节 +-1.78*10^308
为什么要分数据类型:
1.节约内存
2.方便访问
C语言中逻辑运算符
注意:计算机中用补码来存储数据,只有通过补码运行结果才是正确的。
首先需要清楚左值和右值
左值(lvalue): 可以被修改的值称为左值 可以放在=左边的变量
右值(rvalue): 不可以被修改的值不能放在 = 左边的值称为右值
**
右值基本类型:
字符常量 整数常量 浮点常量 表达式 a+b +a ++a
1.操作运算符
1).+ 算数加:
1. int + int 结果是int类型 需要注意数据溢出。
2). - 算数减
3). * 算数乘
4). / 算数除:
1. 对于int类型来说 整除 int/int 结果只会是 int。
2. float f = 10/4; 输出结果为2.00。
3. 除数不能为0 但允许是0.0。
f = 10/0; 会有编译警告 运行核心已转储
f = 10/0.0; 输出inf(极大或者极小)
5). % 取余运算符:
1.取余两边的操作数必须都是 整数 (不可以是浮点数)。
2.任何数据不能对0取余(%右边不能为0。
**注意**:
1.整数字面值如果是[-2^31,2^31 -1] 默认是int类型
int类型数据运算时得到的结果是int类型
2.不同的数据类型进行运算
低字节的数可以隐式转换成高字节的数据
对于有符号的数扩充 符号位
对于无符号的数扩充 0
3.unsigned 和 signed类型数据进行运算时 把 signed 数据转换为 unsigned
执行以下代码时:
int a = -16;
unsigned int b = 10;
if(a+b>=0){
}
恒成立的 int+unsigned 结果为 unsigned类型
2.自增减运算符
1). ++ 自增运算符:
1.自增运算符的操作数必须是左值。
2.操作数可以使任意类型,但一般都用于整数类型。
3.a++与++a的区别:
b = ++a : a=a+1;b=a 先进行自增操作,后计算结果。
b = a++: b=a;a=a+1 先计算表达式的结果,在进行自增操作。
如果单独的a++; ++a; 没有区别,甚至a++会被编译器会被优化成++a。
4.特殊的使用方法:
+++a; ++++a; //错误的
+a; ++a;
a+++b; //错误的
a + ++b; //正确的 三个加号 必须有空格
+ ++a; //正确
注意:不要在同一个表达式中对同一个操作数进行多次自增减运算不同的编译器或者操作平台会有不同的解释。
2). -- 自减运算符:
遵循规则基本与自增是一样的
3.关系运算符 比较运算符
< <= > >= == !=
1.关系运算符的结果只有0和1 假和真。在C语言中,一个 = 是一个赋值语句,两个 = 是比较是否相等(比较运算符)。
2.关系运算符如果出现在同一个表达式中,从左往右计算每一个关系运算符的结果。
特殊形式:
int a = 5;
int f = 1<a<3; //恒为1
因为1<a,要么是0要么是1,一定小于3,因此最后输出结果一定为1。
4.逻辑运算符
&& || !
逻辑运算符用于连接多个多个逻辑值 或者 关系表达式的,最终表达式的结果为1或者0。
C89中没有true 和 false,但<stdbool.h>里用宏定义了ture 和 false 本质上是1和0
&& || !取反
if(1<a && a<5)才表示 a在(1,5)区间
&& 逻辑与
|| 逻辑或
! 逻辑非
C语言中表示
假:数值0 0.0000 '\0' NULL
真:除以上任何值都表示真
短路特性:
1.&& 连接的多个表达式,如果&&前面的表达式的结果为假,则后面的表达式的值不再计算
2. || 连接的多个表达式,如果||前面的表达式的结果为真,则后面的表达式的值不再计算
3. &&的优先级在混合运算中高于||
例如: int a = 0,b = 0,c = 0;
int x = ++a>0||b++>0&&++c>0;
相当于 x = ++a>0||(b++>0&&++c>0)
a = 0,b = 0,c = 0;
x = a++>0&&++b>0||++c>0;
相当于 x = (a++>0&&++b>0)||++c>0
if(1<a && a<5) 才是表示 a在(1,5)区间
&& 逻辑与
a b a&&b
真 真 真
真 假 假
假 真 假
假 假 假
|| 逻辑或
a b a&&b
真 真 真
真 假 真
假 真 真
假 假 假
! 逻辑非
a !a
真 假
假 真
C语言中表示假:
0 0.0000 '\0' NULL
除以上任何值都表示真
1 3.14 'a' 0x3 '\r'
5.位运算符
& ! ^ ~ >> <<
位运算符是指对数据按二进制位进行计算
& 按位与
如果有二进制 0和1 则
1&1 = 1
1&0 = 0
0&1 = 0
0&0 = 0
十进制的数:
13&7 = 5 -7&44 = 40
0000 1101 1111 1001 负数在计算机中需要补码 = 反码+1
0000 0111 0010 1100
---------- ---------
0000 0101 = 5 0010 1000 = 40
推论:
num & -1 = num
xxxxxxxxxxxxxxxxxxxxxx num
1111111111111111111111 -1
----------------------------
xxxxxxxxxxxxxxxxxxxxxx num
num& 0 = 0
判断一个数是否是偶数:
num % 2 ==0
或者
num & 1 ==0
二进制最低为0则为基数 最低位为1则为偶数
| 按位或
如果有二进制 0和1 则
1|1 = 1
1|0 = 1
0|1 = 1
0|0 = 0
十进制的数:
13|7 = 15 -7|44 = -3
0000 1101 1111 1001 负数在计算机中需要补码 = 反码+1
0000 0111 0010 1100
---------- ---------
0000 1111 = 15 1111 1101 = -3 负数需要反码加1
推论:
num | -1 = -1
xxxxxxxxxxxxxxxxxxxxxx num
1111111111111111111111 -1
----------------------------
1111111111111111111111 -1
num | 0 = 0
^ 按位异或 (异1:不同则为1)
如果有二进制 0和1 则
1^1 = 0
1^0 = 1
0^1 = 1
0^0 = 0
13^7 = 10 -7^44 = -43
0000 1101 1111 1001 负数在计算机中需要补码 = 反码+1
0000 0111 0010 1100
---------- ---------
0000 1010 = 10 1101 0101 = -43 负数需要反码加1
推论:
num^num = 0
num^-1 = ~num =~(num+1) 按位取反
0010100011
1111111111
----------
1101011100
~ 按位取反
~0 = 1
~1 = 0
推论:
~num = -(num+1)
负数在计算机内存中是以补码形式存在,等于其正数按位取反
>> 按位右移
右边移出的位舍弃,左边空出的位补(有符号的数补符号位,无符号补0)
每向右移一位相当于除与2 (-1除外)
向右移的位数仅限于[0-31] 超出范围会对32求余
例如1314 >> 34
1314 >> 2
1314 >> 34%32
<< 按位左移
左边移出的位舍弃,右边空出的位补0
每向左移一位相当于乘以2
运算符的优先级:
算术运算符 > 位运算符(取反除外)
算术运算符 > 关系运算符 > 逻辑运算符
交换两个整数的值:
a = a + b; a^=b;
b = a - b; b^=a;
a = a - b; a^=b;
a = a^b;
b = a^b;
a = a^b;
6.赋值运算符
+= -= *= /= &= |= ^= >>= <<=
混合赋值运算符 除了 = 剩下的那个运算符必须是双目运算(有两个操作数)
a *= b; = a= a*b;
a = 10; b = 10;
a = b += 20;
7.三目运算符
?:
expr?expr1:expr2
expr结果如果为真则取expr1否则取expr2
8.sizeof
1.sizeof是操作符,不是函数
2.sizeof是求变量或者类型或者表达式结果所占内存的字节大小
3.sizeof如果操作数是类型 一定要加上小括号()
4.sizeof只关心表达式结果 并不会计算表达式'a'+'c'结果类型为int
5.sizeof(expr) expr是一个多类型表达式时,只关心最宽的字节类型
6.sizeof(函数名) 函数名没有小括号 始终为1
7.size(函数名()) 函数名有小括号 结果等于 函数数返回值类型的字节宽度
8.sizeof9(指针) 结果必为4
指针 == 内存地址
9.其他杂项
, . * & -> []
,: 分隔一条语句中的多个表表达式,多个表达式都会从左往右逐一计算
.: 结构体 或者 联合 成员访问运算符
->: 结构体 或者 联合 指针 访问成员运算符
[]: 数组下标访问运算符
*: 指针取值 运算符
&: 变量取址 运算符
重点:
1.所有数据都是有字节宽度大小的 在赋值在运算过程中 都可以发生变化
2.隐式类型转换
char --> int --> long --> double
float --> double
short --> int
signed --> unsigned