【C/C++】系列文章目录
第三节【C/C++】初识C语言语句、函数、数组、运算符、关键字
文章目录
前言
本章节是对前述章节运算符部分的补充,涉及sizeof和数组类型,移位运算符规则,整型提升,类型转换等。
一、运算符
1.左移操作符
移位规则:
左边抛弃、右边补0
n的值不发生变化。
2.右移操作符
移位规则:首先右移运算分两种:1. 逻辑移位左边用0填充,右边丢弃2. 算术移位左边用原该值的 符号位填充,右边丢弃
我们看下vs2019中是哪种右移结果。
对于移位运算符,不要移动负数位,这个是标准未定义的。
int num = 10;
num>>-1;//error
3.按位异或
//不允许创建临时变量,交换两个整数的内容
int main()
{
int a = 60;
int b = 80;
printf("a = %d,b= %d\n", a, b);
//方法:1:
a = a+b;
b = a-b;
a = a-b;
printf("a = %d,b= %d\n", a, b);
//方法2:
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a = %d,b= %d\n", a, b);
return 0;
}
以上两种方法都可以将a和b的两个值交换,但是方法的1的弊端在于如果a和b的两个数很大,相加会有超出int的表示范围的可能(即溢出)。所以方法2更好一些。
a^a = 0;
x^0 = x;
- 任何一个数按位异或它自己得到的都是0;
- 任何一个数按位异或0得到它自己。
4.sizeof和数组
int main()
{
int arr[10] = { 0 };
char ch[10] = { 0 };
printf("%d\n", sizeof(arr)); //40
printf("%d\n", sizeof(ch));//10
printf("%d\n", sizeof(int[10]));//40
printf("%d\n", sizeof(char[10]));//10
return 0;
}
我们知道sizeof可以计算变量大小,既可以使用sizeof(变量名),又可以使用sizeof(类型),计算大小。
从上面代码可以知道,arr是变量的名称,int [10]是arr数组的类型。
int main()
{
short s = 5;
int a = 10;
printf("%d\n", sizeof(s = a + 2));
printf("%d\n", s);
}
s没有被重新计算赋值。
结论:
sizeof括号中的表达式不参与运算。
二、表达式求值
表达式求值的顺序一部分是由操作符的优先级和结合性决定。
同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。
每个表达式都有两个属性:
- 值属性
- 类型属性
1.隐式类型转换
C的整型算术运算总是至少以缺省整型类型的精度来进行的。
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
整型提升的意义:
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度
一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长
度。
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令
中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转
换为int或unsigned int,然后才能送入CPU去执行运算。
如何进行整型提升呢?
整型提升是按照变量的数据类型的符号位来提升的。
- 正数补0
- 负数补1
- 无符号数补0
int main()
{
char a = 5;
char b = -1;
char c = a + b;
return 0;
}
- a和b的值被提升为普通整型;
- 再执行加法运算;
- 加法运算完成之后,结果将被截断,然后再存储于c中。
char类型和short类型只要参与运算就会发生整型提升,如下:
2.算术转换
某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换。
long double
double
float
unsigned long int
long int
unsigned int
int
- 向精度更高的转换
- 向字节更长的转换
float f = 3.14;
int num = f;//隐式转换,会有精度丢失
三、操作符属性
复杂表达式的求值有三个影响的因素。
1. 操作符的优先级
2. 操作符的结合性
3. 是否控制求值顺序。
两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。
部分操作符优先级
四、注意
- 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
- % 操作符的两个操作数必须为整数。返回的是整除之后的余数。
- 移位操作符的操作数只能是整数。
- 对于移位运算符,不要移动负数位,这个是标准未定义的。
- 全局变量定义时未初始化,默认值是0。
总结
sizeof和数组类型,操作符运算优先级,移位运算符移位规则,类型转换,整型提升。