C语言整型提升、算术转换、操作符的属性

C语言整型提升、算术转换、操作符的属性


整型提升

  C语言在进行整型算术运算时,总是把字符型、短整型操作数在使用之前转换为普通整型参与运算。
  整型提升是按照数据类型的符号位来提升的,正数补0,负数补1。如果是无符号的数,高位也是补0。


整型提升的意义:

  表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。


例子:

char a = 10;
00000000 00000000 00000000 00001010  //整型提升
00001010 //a的补码,发生截断只能保存一个字节数据
char b = 125;
00000000 00000000 00000000 01111101	//整型提升
01111101 //b的补码,发生截断只能保存一个字节数据
char res = a + b;
// 整型提升
00000000 00000000 00000000 00001010 
00000000 00000000 00000000 01111101 
00000000 00000000 00000000 10000111 //a + b的结果
//发生截断 res实际存的值是 10000111
printf("%d" , res);
// 整型提升
11111111 11111111 11111111 10000111
11111111 11111111 11111111 10000110
10000000 00000000 00000000 01111001
// 最终结果是 -121

#include 

int main() {

	char num = 10;
	/*
		第一个printf里的num没有参与运算,所以没有整型提升
		第二个以及第三个printf都是一个表达式,参与运算会整型提升,
		所以是4个字节
	*/
	printf("%d\n", sizeof(num));  // 1
	printf("%d\n", sizeof(+num)); // 4
	printf("%d\n", sizeof(-num)); // 4

	return 0;
}

算术转换(自动类型转换)

  1.在进行运算时,不同类型的数据要先转换成相同类型在进行运算。
  2.精度低的数据类型向精度高的数据类型转换。

必做的转换

char -> int
short -> int
float -> double

运算对象的类型不同,由低向高转换

int -> unsigned int -> long -> unsigned long -> float -> double -> long double

例子:

int main () {
	int a = 10;
	short b = 20;
	float c = 1.5;
	double d = 5.6;
	printf("%lf" , a + b - c / d); // 这个表达式最后的类型是double
	
	return 0;
}

操作符的属性

运算符 名称或含义 使用形式 结合方向
() 圆括号 (表达式)
函数名(形参)
左到右
[] 下标引用 数组名[常量表达式] 左到右
. 结构体访问成员 结构体.成员 左到右
-> 结构体指针访问成员 结构体指针->成员 左到右
- 负号运算符 -表达式 右到左
+ 正号运算符 -表达式 右到左
++ 自增运算符 ++表达式
表达式++
右到左
- - 自增运算符 –表达式
表达式–
右到左
* 解引用运算符 *指针变量 右到左
& 取地址运算符 &变量名 右到左
! 逻辑非运算符 !表达式 右到左
~ 按位取反运算符 ~表达式 右到左
sizeof 判断类型、变量字节数 sizeof(表达式) 右到左
(类型) 强制类型转换 (类型)变量 右到左
/ 表达式/表达式 左到右
* 表达式*表达式 左到右
% 取模 表达式%表达式 左到右
+ 表达式+表达式 左到右
- 表达式-表达式 左到右
<< 左移 表达式<<表达式 左到右
>> 右移 表达式>>表达式 左到右
> 大于 表达式>表达式 左到右
>= 大于等于 表达式>=表达式 左到右
< 小于 表达式<表达式 左到右
<= 小于等于 表达式<=表达式 左到右
== 等于 表达式==表达式 左到右
!= 不等于 表达式!=表达式 左到右
& 按位与 表达式&表达式 左到右
^ 按位异或 表达式^表达式 左到右
| 按位或 表达式|表达式 左到右
&& 逻辑与 表达式&&表达式 左到右
|| 逻辑或 表达式||表达式 左到右
?: 条件运算符 表达式1?表达式2:表达式3 右到左
= 赋值运算符 变量=表达式 右到左
+= 加赋值运算符 变量+=表达式 右到左
-= 减赋值运算符 变量-=表达式 右到左
*= 乘赋值运算符 变量*=表达式 右到左
/= 除赋值运算符 变量/=表达式 右到左
%= 模赋值运算符 变量%=表达式 右到左
<<= 左移赋值运算符 变量<<=表达式 右到左
>>= 右移赋值运算符 变量>>=表达式 右到左
&= 按位与赋值运算符 变量&=表达式 右到左
^= 按位异或赋值运算符 变量^=表达式 右到左
|= 按位或赋值运算符 变量|=表达式 右到左
, 逗号运算符 (表达式,表达式,表达式,…) 左到右

注:即使我们知道了操作符的优先级和结合性,但是对于一些奇怪的表达式,根据计算路径的不一致,我们依然求不出唯一值。

你可能感兴趣的:(c语言,学习,开发语言)