编译时间和运行态时间交换的优缺点

简介: 编译时间和运行态时间交换的优缺点

前言

(1)前几天,我刷视频无意之间看到一个视频说,sizeof(a++),这个a是会自增吗?

(2)如果有经验的人肯定会说,不会自增,这是常识。那么将这句话转化为汇编之后会发生什么呢?为什么a不会进行自增呢?


将sizeof(a++)转换为汇编

(1)既然我们要探究为什么sizeof(a++)中的a不会进行自增,那么最好的办法就是,将C语言转换成汇编,看看最终执行效果


(2)这是为什么呢?我去查阅了C语言标准,其中有这么一段话:

When applied to an expression, sizeof does not evaluate the expression (i.e. the expression is an unevaluated operand) (since C++11), and even if the expression designates a polymorphic object, the result is the size of the static type of the expression. Lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversions are not performed. Temporary materialization, however, is (formally) performed for prvalue arguments: the program is ill-formed if the argument is not destructible. (since C++17)

翻译结果:当应用于表达式时,sizeof不计算表达式 (即表达式是未计算的操作数) (C++11 起),并且即使表达式指定多态对象,结果也是表达式的静态类型的大小。不执行左值到右值、数组到指针或函数到指针的转换。然而,临时物化(正式)是对纯右值参数执行的:如果参数不可破坏,则程序是格式错误的。 (自 C++17 起)

(3)由此可见,C语言标准决定了sizeof之后的式子是不会进行任何的计算的。


为什么sizeof后面的式子不进行计算

用编译器的时间换运行态的时间

(1)这个时候可能有人就会有疑问了。为什么sizeof后面的式子不进行计算呢?

(2)通过和大佬们交流,我得知了一个名词,叫做用编译器的时间换运行态的时间。

(3)这个时候可能有人就有疑惑了。编译器时间是什么呢?运行态时间又是什么呢?我在stack overflow上找到了非常好的解释。

<1>编译时:您(开发人员)编译代码的时间段。

<2>运行时间:用户运行您的软件的时间段。

(4)当你调用sizeof 的时候,核心目的是为了知道这个变量所占几个字节。那么,==一个数据,进行自增或者自减,是不会影响到他的类型的,他占据几个字节也不会有影响。==所以为了提高代码执行速度,我们可以只进行判断变量a 的所占字节即可,他的运算是可有可无的。

时间交换可能会产生的不良后果

(1)现在,我们知道了可以使用编译器时间来换取运行时间,来提高用户体验,那么这样做,真的就非常完美了吗?

(2)答案肯定是不,为什么呢?因为,想单片机程序,如果我想让一个单片机进行一个1ms的延时。于是我就让变量a进行不断的自增,最终实现延时效果。

 //假设这是一个延时1ms的程序
void delay(void)
{
  int a;
  for(a=0;a<50000;a++);
}


(3)但是,如果是玩过MSP430的同学就会发现,不对,有问题。这个并没有延时效果,我们会需要调整编译器优化等级才可能出现延时效果。

(4)这是为什么呢?原因很简单,如果你编译器优化等级过高,而编译器发现for(a=0;a<50000;a++);这个语句什么都没做,可能就会放弃掉这个语句。最终导致无法产生想要的延时效果。

(5)编译器除了放弃一些认为不用的程序以外,还做了什么吗?举个例子,假如一个程序里面有一个运算式子:a = 2+2+4 ,那么编译器会直接将2+2+4计算出来,并且将8传给a。这样就能够降低运行状态的时间,提高用户体验。


总结

(1)sizeof(a++)这个运算式子算是编译器时间换运行态时间的一种方式,这样做能够提高用户体验。

(2)但是,有可能程序员一开始的目标就是要用来延时的,所以容易产产生负面效果。

(3)因此,我们应该对这个有充分的了解。根据需求做决定。

目录
相关文章
|
8月前
|
Go 数据库
sync.Once-保证运行期间的某段代码只会执行一次
sync.Once-保证运行期间的某段代码只会执行一次
46 0
|
6天前
在程序运行过程中,线程的状态是什么?进来看看就通透了
在程序运行过程中,线程的状态是什么?进来看看就通透了
34 0
|
存储 Java 编译器
JVM特点,基础结构与执行周期
虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。
158 0
JVM特点,基础结构与执行周期
|
监控
【多线程:两阶段终止模式】volatile版本
【多线程:两阶段终止模式】volatile版本
90 0
DHL
|
存储 算法 Java
卷起来,突破35岁焦虑,动画演示CPU记录函数调用过程,进互联大厂如此简单
通过这篇文章,能够了解到 方法如何调用 、 方法执行完之后如何返回、 内存如何记录方法调用过程。方法调用和返回过程涉及到了,虚拟机栈、程序计数器、局部变量表、操作数栈、方法返回地址、动态链接 等等内容
DHL
126 0
卷起来,突破35岁焦虑,动画演示CPU记录函数调用过程,进互联大厂如此简单
|
IDE 物联网 测试技术
项目实战:Qt并发服务器通讯,受同一时刻最大线程数限制(笔者本本同一时刻600多)
项目实战:Qt并发服务器通讯,受同一时刻最大线程数限制(笔者本本同一时刻600多)
项目实战:Qt并发服务器通讯,受同一时刻最大线程数限制(笔者本本同一时刻600多)
|
Java
在程序里面,时间真的发生了344秒的倒流。(中)
在程序里面,时间真的发生了344秒的倒流。(中)
95 0
在程序里面,时间真的发生了344秒的倒流。(中)
|
Java 数据库
在程序里面,时间真的发生了343秒的倒流。(上)
在程序里面,时间真的发生了343秒的倒流。(上)
158 0
在程序里面,时间真的发生了343秒的倒流。(上)
|
Java 数据库
在程序里面,时间真的发生了345秒的倒流。(下)
在程序里面,时间真的发生了345秒的倒流。(下)
102 0
在程序里面,时间真的发生了345秒的倒流。(下)