当前位置: 首页 > news >正文

鹏哥C语言72---操作符与表达式求值

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

//---------------------------------------------------------------------------------------------------------------操作符-12. 表达式求值
//表达式求值的顺序一部分是由  操作符  的优先级和结合性  决定。
//同样, 有些表达式的操作数在求值的过程中可能需要转换为其他类型。

//-------------------------------------------------------------------------------------------------------12.1隐式类型转换
//C的整型算术运算总是至少以缺省(默认)整型类型的精度来进行的。
//为了获得这个精度, 表达式中的字符和短整型操作数在使用之前被转换为普通整型, 这种转换称为整型提升。

int main()
{char a = 5;char b = 126;char c = a + b; //运算前需要先把 a,b整型提升为 int 类型printf("%d\n", c);return 0;
}

整型提升的意义 :
表达式的整型运算要在CPU的相应运算器件内执行, CPU内整型运算器(ALU)的操作数的字节长度,
一般就是int的字节长度, 同时也是CPU的通用寄存器的长度。

因此, 即使两个char类型的相加, 在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度

通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令
中可能有这种字节相加指令)。所以, 表达式中各种长度可能小于int长度的整型值, 都必须先转
换为int或unsigned int, 然后才能送入CPU去执行运算。
 

如何进行整体提升呢?
整形提升是按照变量的数据类型的符号位来提升的

//-------------------------------------------------负数的整形提升
char c1 = -1
变量c1的二进制位(补码)中只有8个比特位:
1111111
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为1
提升之后的结果是:
11111111111111111111111111111111

//-------------------------------------------------正数的整形提升
char c2 = 1;
变量c2的二进制位(补码)中只有8个比特位:
00000001
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001
//------------------------------------------------无符号数整型提升,高位补0

 //-----------------------------------------------------------------------整型提升举例1

int main()
{char a = 5;//5的2进制序列,4个字节,32bit//00000000000000000000000000000101  5的补码//char a---------------00000101char b = 126;//126的2进制序列,4个字节,32bit//00000000000000000000000001111110  126的补码//char b--------------01111110char c = a + b; //char a---------------00000101//char b---------------01111110//表达式中的字符和短整型操作数在使用之前被转换为普通整型//00000000000000000000000000000101---a//00000000000000000000000001111110---b//00000000000000000000000010000011---c//char c---------------10000011//负数整型提升//11111111111111111111111110000011---c的补码//转为原码//10000000000000000000000001111101----   -125printf("%d\n", c); // -125return 0;
}

//-----------------------------------------------------------------------整型提升举例2

int main()
{char a = 0xb6;short b = 0xb600;int c = 0xb6000000;if (a == 0xb6) // a整型提升了printf("a"); //不打印if (b == 0xb600) // b整型提升了printf("b"); //不打印if (c == 0xb6000000) //c 不需要整型提升printf("c"); //打印return 0;
}

//-----------------------------------------------------------------------整型提升举例3

int main()
{char c = 1;printf("%u\n", sizeof(c));//1printf("%u\n", sizeof(+c));//4printf("%u\n", sizeof(-c)); //4return 0;}

//-------------------------------------------------------------------------------------------------------12.2 算术转换
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类
型,否则操作就无法进行。下面的层次体系称为寻常算术转换。
long double
double
float
unsigned long int
long int
unsigned int
int

//如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。
//但是算术转换要合理,要不然会有一些潜在的问题。


//-------------------------------------------------------------------------------------------------------12.3 操作符的属性
复杂表达式的求值有三个影响的因素。
1.操作符的优先级
2.操作符的结合性
3.是否控制求值顺序
两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。

//操作符优先级
//表格
//-------------------------------------------------------------------问题表达式/代码

int main()
{3 + 2 * 4 + 5;//优先级只在相邻操作符中考虑3 * 4 + 5 * 2 + 8 * 5; //有多种求值路径----------是问题表达式 1int c = 2;c+--c; //------------------------------问题表达式 2int i = 10;i = i-- - --i * (i = -3) * i++ + ++i; //---------- 问题表达式 3 printf("i =%d\n", i);return 0;
}

//----------------------------------------问题代码 4

int fun()
{static int count = 1;return ++count; //由于 static,每次进入函数,count都不会销毁,每次调用函数,都会返回不同的count值
}
int main()
{int answer;answer = fun() - fun() * fun();printf("%d\n", answer);//输出多少?return 0;
}

// ----------------------------------------问题代码 5

int main()
{int i = 1;int ret = (++i) + (++i) + (++i); //求解路径不唯一printf("%d\n", ret);  // b是多少?printf("%d\n", i);  // i是多少?//不同编译器/服务器下,答案不同//因为求值路径不唯一,不同不同编译器/服务器选择的计算路径不同return 0;
}

//总结:我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的。
 


http://www.mrgr.cn/news/46456.html

相关文章:

  • Eamon.MeituanDotnetSDK 美团C# .Net SDK开源啦
  • 我的年度总结
  • 【SH】Xiaomi9刷Windows10系统研发记录 、手机刷Windows系统教程、小米9重装win10系统
  • 为什么要分为大端和小端
  • OpenCV相机标定与3D重建(55)通用解决 PnP 问题函数solvePnPGeneric()的使用
  • Linux:动态库和静态库
  • 【C/C++】错题记录(七)
  • 引领行业发展,大北互集团携手纷享销客共建营销数字化发展新引擎
  • 76.【C语言】perror函数介绍
  • Android设置边框圆角
  • xtu oj Balls
  • secure boot 部分知识
  • 20.安卓逆向-frida基础-hook分析调试技巧2-hookDES
  • web1.0,web2.0,web3.0 有什么区别 详解
  • Linux deepin系统通过编辑crontab来设置定时任务---定时关机
  • 使用pycharm的sftp功能远程操控服务器的时候,遇到了一些问题:Local path ’ ’ is outof project
  • 工厂车间|基于springBoot的工厂车间系统设计与实现(附项目源码+论文+数据库)
  • 极客兔兔Gee-Cache Day6
  • 单片机(学习)2024.10.9
  • 《基于FreeRTOS的STM32超声波智能避障平衡小车,实现了小车的自平衡、超声波避障以及通过智能手机远程控制的功能》+源代码+文献资料+文档说明
  • 【AI知识点】泛化(Generalization)与过拟合(Overfitting)
  • 安全帽未佩戴预警系统 劳保防护用品穿戴监测系统 YOLO
  • RK3588S系统导出和烧入新板子
  • 服务器平均响应时间和数据包大小关系大吗?
  • 3.1 显示层技术演变
  • 自由学习记录(4)