数据类型的转换:
1. 自动转换:遵循一定的规则,由编译系统自动完成,占用字节少的向占用多的类型转换,保证精度不降低;
#include <iostream>
#include <stdio.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
void test01()
{
int data01=-20;
unsigned data02=10;
/*有符号data01和无符号data02参加计算时,会先将data01转换成无符号
(data01转换成它自身的补码,-20的补码数是很大一个正数)
*/
if(data01+data02>0)
{
printf(">0\n");
}
else
{
printf("<0\n");
}
}
void test02()
{
char ch='a';
short data=20;
printf("%d\n",sizeof(ch+ch)); //4
printf("%d\n",sizeof(ch+data)); //4
printf("%d\n",sizeof(data+data)); //4
}
int main(int argc, char** argv) {
test01();
test02();
return 0;
}
//结果是 >0
- int + double 其结果是double类型,因为int在加的时候自动转换为double类型;
- char类型本身1字节范围是0~255,容易内存溢出;在做运算时,系统自动将其转化为int类型;
2.强制类型转换:把表达式的运算结果强制转换成所需的数据类型,有一定的数据丢失风险,由程序员承担
(类型说明符)表达式:把表达式的运算结果强制转换成类型说明符所表示的类型;
(float) a //把a转换成实型;(int)(x+y) //把x+y的结果转换成整型;
赋值的结果由接收方决定;强制类型转换只是临时的转换,当前语句中有效,但不会更改原先的值
void test03()
{
float x=3.14f;
int j=0;
j=x;
j=(int)x; //将x的整数部分给j
printf("x=%d\n,j=%d\n",x,j);
}
int main(int argc, char** argv) {
test03();
return 0;
}
// 结果 x=3.14,j=3 因为j的类型是int,赋值实型给j,j只获取整数的部分;
运算符:
- 用算术运算符将运算对象(操作数)连接起来的,符合C语言规则的式子,称为c运算表达式
- 运算对象包括 常量,变量,函数值等;
- 常见的运算符:
- 算术运算符:+ - * / 取整(a/b a b必均为整数) %取余; 5/2.0f 此为除法;
- 关系运算符 > < >= <= == !=
- 逻辑运算符 && || !与 或 非
- !1 -->0非真的结果是0假,!0-->1,非0假的结果是真1;
- 在C语言中,0为假false,其余数均为真true;
- &&同真为真,同假为假;A&&B 若A为假,则B就不去执行了;如 num=10, (2>3)&&(num=100); //num的值依旧为10;
- A||B 一真为真;均为假则结果假;只要A为真,就不去判断B是否为真了;num=10, (3>2)||(num=100); //num=100得不到执行就结束了,num的值还为10;
- 位运算符 二进制位操作 <<左移 >>右移 &按位与 |按位或 ~按位取反 ^按位异或
- 按位与 & 语法:全1为1,其他为0;
- 0111 1011
& 1111 0000 ----》0111 0000 - 特点:和1相与保持不变,和0相与清零;
- 应用场景:将固定位清零;
- 0111 1011
- 按位或 | 语法:有一为1就为1,全0才为0;
- 1010 1010
| 1111 0000 -------》1111 1010 - 特点:和0相或不变,和1相或置1;
- 场景:将固定位置1;
- 1010 1010
- 按位取反 ~ 语法:0变1,1变0;
- ~1010 1010 ----》0101 0101 配合 & | 使用;
- 按位异或 ^ 语法:相同为0,不同为1
- 1010 1010
^ 0000 1111 ------>1010 0101 - 特点:与0异或保持不变,和1异或取反;
- 场景:将固定位,发生高低电频反转;
- 1010 1010
- 左移 << 1010 1100 左移两位 <<2,1010 1100 ,补两位0 1011 0000
- 移动的位数不能超过自身的长度;
- 右移 >> 1010 1100 右移两位>>2,左边空出来的位置 是补1 还是补0
- 右移需先分类:
逻辑右移(右边丢弃左边补0)
算术右移:无符号数,右边丢弃左边补0
有符号数,正数右边丢弃,左边补0,
负数右边丢弃,左边补1 - 右移基本上是右边丢弃左边补0,只有负数且算术右移左边补1;
逻辑右移和算术右移由编译器决定,但是我们可以检测;//案例: 将data的第1 5位清0,第3 4位 置1,其余不变; unsigned char data=1010 1010; //这么写 计算机会认为是十进制很大的数,不是二进制; unsigned char data=0xaa; //1010 1010 /*1. 将data的第1 5清0;按位与 data=data & 1101 1101;阅读性不高 取反 1101 1101 = ~(1010 1010)=~(0010 0000 | 0000 0010), 0010 0000 =0000 0001 <<5 左移5位 0000 0010 =0000 0001 >>1 右移1位 1101 1101 =~(0x01<<5| 0x01>>1); */ data=data & ~(0x01<<5 | 0x01>>1); //一看便知,是第1 和第5位 清0; /*2. 将第3 4位 置1,按位或,data=data | 0001 1000 0001 1000= 0001 0000 | 0000 1000 0001 0000= 0000 0001 <<4 左移4位, 0000 1000= 0000 0001 <<3 左移3位, 0001 1000=(0x01<<4 | 0x01<<3) */ data=data | (0x01<<4 | 0x01<<3);
- 右移需先分类:
- 按位与 & 语法:全1为1,其他为0;
- 赋值运算符 =
int data=3; data*=3+5 //data=data*(3+5) =号右边必须看作是一个整体;
- 条件运算符 ? :表达式1? 值1 : 值2 表达式1为真,整个表达式的值为值1,否则为值2;
- 逗号运算符 , 从左往右结合,结果是最后一个数,data=(3,4,5,6) -->6
- 指针运算符 * &
- 求字节数运算符 sizeof(类型、变量),强制类型转换运算,分量运算符(. ->),下标运算符[ ],函数调用运算符()
- 复合运算符:
- ++i --i 先加减 后使用
- i++ i-- 先使用 后加减
- 运算符的优先级 1-15级 1最高,15最低。
- 优先级别高的先运算;尽量加()区分
算术运算符优先级顺序: 第1级 ()圆括号 []数组下标 .成员运算符 ->指针的指向运算符 自左向右,如a=()[] 第2级 -负号 +正号 ++自增 --自减 !逻辑非 ~按位取反 (t)e类型转换 *p指针运算 &x求变量地址 sizeof求 类型变量长度 自右向左 第3级 *乘 /除 %取余 自左向右 第4级 +加 -减 自左向右 第5级 <<左移 >>右移 第6级 <小于 <=小于等于 >大于 >=大于等于 自左向右 第7级 ==等于 !=不等于 自左向右 第8级 &按位与 自左向右 第9级 ^按位异或 自左向右 第10级 |按位或 自左向右 第11级 &&逻辑与(并且) 自左向右 第12级 ||逻辑或(或者) 自左向右 第13级 ?: i+j?e2:e3 自右向左 第14级 =赋值,+=加赋值 —=减赋值 *=乘赋值 /=除赋值 %=取余赋值 <<=左移赋值 >>=右移赋值 &=按位或赋值 ^=按位异或赋值 != 自右向左 第15级 ,逗号 e1,e2,e3 --->e3 自左向右
- 若优先级同等时,则按运算符的结合性所规定的方向处理;
- + - * /
- 优先级别高的先运算;尽量加()区分