运行时vs.编译时

运行时和编译时的区别是什么?

344384 次浏览

编译时:你作为开发人员编译代码的时间段。

运行时:用户运行你的软件的时间段。

你需要更明确的定义吗?

嗯,好吧,运行时是用来描述程序运行时发生的事情。

编译时间用来描述在构建程序(通常由编译器)时发生的事情。

运行时是指在运行程序时发生的事情。

编译时是指在编译程序时发生的事情。

基本上,如果你的编译器能在“编译时”找出你的意思或一个值是什么,它就能硬编码到运行时代码中。显然,如果你的运行时代码每次都要进行计算,那么它会运行得更慢,所以如果你能在编译时确定一些东西,那就更好了。

如。

常数合并:

如果我这样写:

int i = 2;
i += MY_CONSTANT;

编译器可以在编译时执行这个计算,因为它知道2是什么,MY_CONSTANT是什么。因此,每次执行时,它都不必执行计算。

例如:在强类型语言中,类型可以在编译时或运行时检查。在编译时,这意味着如果类型不兼容,编译器将报错。在运行时,意味着你可以很好地编译你的程序,但在运行时,它会抛出一个异常。

(编辑:以下适用于c#和类似的强类型编程语言。我不确定这是否对你有帮助)。

例如,在运行程序之前,编译器(在编译时)将检测到以下错误,并将导致编译错误:

int i = "string"; --> error at compile-time

另一方面,像下面这样的错误不能被编译器检测到。你将在运行时处收到一个错误/异常(当程序运行时)。

Hashtable ht = new Hashtable();
ht.Add("key", "string");
// the compiler does not know what is stored in the hashtable
// under the key "key"
int i = (int)ht["key"];  // --> exception at run-time

我认为它是错误的,以及什么时候可以发现错误。

编制时间:

string my_value = Console.ReadLine();
int i = my_value;

字符串值不能被赋值为int类型的变量,因此编译器确定在编译时这段代码有问题

运行时间:

string my_value = Console.ReadLine();
int i = int.Parse(my_value);

这里的结果取决于ReadLine()返回的字符串。有些值可以解析为int型,有些则不能。这只能在运行时处确定

编制时间:

在编译时执行的操作在最终程序运行时几乎不会产生任何开销,但在构建程序时可能会产生很大开销。

运行时:

或多或少完全相反。构建时成本小,运行程序时成本大。

从另一边;如果在编译时执行了某些操作,那么它只在您的机器上运行;如果在运行时执行了某些操作,那么它将在用户的机器上运行。

相关性

这一点很重要的一个例子是单元携带类型。编译时版本(如提振。单位我的D版本)最终与使用本机浮点代码解决问题一样快,而运行时版本最终必须打包有关值所在单位的信息,并在每次操作时对它们进行检查。另一方面,编译时版本要求值的单位在编译时已知,不能处理它们来自运行时输入的情况。

编译时和运行时之间的差异是尖头理论家所说的相位区分的一个例子。它是最难学习的概念之一,特别是对于没有太多编程语言背景的人来说。要解决这个问题,我发现问一下很有帮助

  1. 程序满足哪些不变量?
  2. 在这个阶段会出现什么问题?
  3. 如果阶段成功,后置条件是什么(我们知道什么)?
  4. 输入和输出是什么(如果有的话)?

编译时

  1. 程序不需要满足任何不变量。事实上,它根本不需要是一个结构良好的程序。你可以把这个HTML提供给编译器,然后看着它吐出来……
  2. 编译时可能出错的地方:
    • 语法错误
    • Typechecking错误
    • (很少)编译器崩溃
    • 李< / ul > < / > 如果编译器成功,我们知道什么?
      • 这个程序结构良好——无论用什么语言都是一个有意义的程序。
      • 可以开始运行程序了。(程序可能会立即失败,但至少我们可以尝试一下。)
      • 李< / ul > < / >
      • 输入输出是什么?
        • Input是正在编译的程序,加上它需要进口来编译的任何头文件、接口、库或其他巫术。
        • 输出希望是汇编代码或可重定位的目标代码,甚至是可执行程序。如果出现错误,则输出一堆错误消息。
        • 李< / ul > < / >

运行时

  1. 我们对程序的不变量一无所知——它们是程序员放入的任何东西。运行时不变量很少由编译器单独执行;它需要程序员的帮助。
  2. 可能出错的有运行时错误:

    • 除以0
    • 取消对空指针的引用
    • 内存不足

    程序本身也可能检测到错误:

    • 试图打开一个不存在的文件
    • 试图找到一个网页,发现一个所谓的URL不是良好的形式
    • 李< / ul > < / >
    • 如果运行时成功,则程序结束(或继续运行)而不会崩溃。
    • 输入和输出完全取决于程序员。文件,屏幕上的窗口,网络数据包,发送到打印机的作业,应有尽有。如果程序发射导弹,这是一个输出,它只发生在运行时:-)

对于S.O.来说,这不是一个好问题(这不是一个特定的编程问题),但总的来说,这不是一个坏问题。

如果您认为这是微不足道的:那么读时与编译时的区别是什么呢?什么时候这是一个有用的区别?编译器在运行时可用的语言呢?Guy Steele(不是笨蛋,他)在CLTL2中写了7页关于EVAL-WHEN的内容,CL程序员可以使用它来控制这一点。2句话对于定义来说勉强足够,它本身远远不够解释

总的来说,这是语言设计者试图避免的一个棘手问题。 他们经常说:“这是一个编译器,它做编译时的事情;之后的一切都是运行时,玩得开心”。C语言被设计为易于实现,而不是最灵活的计算环境。当您在运行时没有可用的编译器,或者没有能力轻松地控制表达式何时求值时,您往往会在语言中使用黑客来伪造宏的常见用法,或者用户提出设计模式来模拟拥有更强大的结构。一种易于实现的语言肯定是一个有价值的目标,但这并不意味着它是编程语言设计的最终目标。(我不怎么使用EVAL-WHEN,但我无法想象没有它的生活)

关于编译时和运行时的问题空间是巨大的,而且在很大程度上仍未被探索。这并不是说S.O.是进行讨论的正确场所,但我鼓励人们进一步探索这一领域,特别是那些对它应该是什么没有先入为主概念的人。这个问题既不简单也不愚蠢,我们至少可以给检察官指出正确的方向。

不幸的是,我不知道任何好的参考资料。CLTL2稍微讲了一下,但对于学习它并不是很好。

将源代码转换为“屏幕|磁盘|网络”可以(大致)以两种方式发生;称之为编译和解释。

编译程序中(例如c和fortran):

  1. 源代码被输入到另一个程序(通常称为编译器),该程序生成一个可执行程序(或一个错误)。
  2. 运行可执行文件(通过双击它,或在命令行上键入它的名称)

在第一步发生的事情被称为在“编译时”发生,在第二步发生的事情被称为在“运行时”发生。

解释程序中(例如MicroSoft basic(在dos上)和python(我认为)):

  1. 源代码被输入到另一个程序(通常称为解释器),该程序直接“运行”它。在这里,解释器充当程序和操作系统(或非常简单的计算机中的硬件)之间的中间层。

在这种情况下,编译时和运行时之间的差异很难确定,而且与程序员或用户的关系也小得多。

Java是一种混合,代码被编译成字节码,然后在虚拟机上运行,虚拟机通常是字节码的解释器。

还有一种中间情况,即程序被编译为字节码并立即运行(如在awk或perl中)。

这里是对“运行时和编译时的区别?”这个问题的回答的扩展。——与运行时和编译时相关的管理费用的差异?

产品的运行时性能通过更快地交付结果来提高其质量。产品的编译时性能通过缩短编辑-编译-调试周期来提高其时效性。然而,运行时性能和编译时性能都是实现及时性质量的次要因素。因此,只有当整体产品质量和时效性得到改善时,才应该考虑运行时和编译时性能的改进。

进一步阅读在这里的一个很好的来源:

编制时间:

在编译时所做的事情在最终程序运行时几乎不会产生任何成本,但在构建程序时可能会产生很大成本。 运行时:< / p >

或多或少完全相反。构建时成本小,运行程序时成本大。

从另一边;如果在编译时执行了某些操作,那么它只在您的机器上运行;如果在运行时执行了某些操作,那么它将在用户的机器上运行。

我一直认为它与程序处理开销以及它如何影响性能有关,如前所述。一个简单的例子是,在代码中定义对象所需的绝对内存。

一个定义的布尔值占用x个内存,然后在编译后的程序中,不能更改。当程序运行时,它确切地知道为x分配多少内存。

另一方面,如果我只是定义了一个泛型对象类型(即一种未定义的占位符或可能是一个指向一些巨大blob的指针),我的对象所需的实际内存是不知道的,直到程序运行,我分配了一些东西给它,因此它必须评估和内存分配等,然后将在运行时动态处理(更多的运行时开销)。

如何动态处理它取决于语言、编译器、操作系统、你的代码等等。

然而,在这一点上,它实际上取决于您使用运行时和编译时的上下文。

我们可以将其分为两大类静态绑定和动态绑定。它取决于何时与相应值绑定。如果引用是在编译时解析的,那么它是静态绑定;如果引用是在运行时解析的,那么它是动态绑定。静态绑定和动态绑定又称早期绑定和后期绑定。有时也称为静态多态和动态多态。

约瑟夫Kulandai‏。

根据前面类似的问题运行时错误和编译器错误的区别是什么?的答案

编译或编译时错误是由于键入错误而发生的错误,如果我们不遵循任何编程语言的正确语法和语义,则编译器将抛出编译时错误。他们不会让你的程序执行一行,直到你删除所有的语法错误或直到你调试编译时错误 示例:C中缺少分号或将int错误地输入为Int.

运行时错误:运行时错误是程序处于运行状态时产生的错误。这些类型的错误将导致您的程序出乎意料地运行,甚至可能杀死您的程序。它们通常被称为例外。
示例:假设您正在读取一个不存在的文件,将导致运行时错误。< / p >

在这里阅读有关所有编程错误的更多信息

运行时和编译时的主要区别是:

  1. 如果代码中有任何语法错误和类型检查,则抛出编译时错误,而-as运行时:它在执行代码后进行检查。 例如:李< / >

int a = 1 Int b = a/0;

这里的第一行末尾没有分号——在执行操作b时执行程序后,>编译时错误,结果是无限的——>运行时错误。

  1. 编译时不会查找代码提供的功能的输出,而运行时则会。

在简单的文字差异b/w编译时间&运行时。

编译时:开发人员以.java格式编写程序;转换为类文件的字节码,在编译过程中发生的任何错误都可以定义为编译时错误。

运行时:生成的.class文件被应用程序用于它的附加功能。逻辑被证明是错误的,并抛出一个错误,这是一个运行时错误

这里有一个非常简单的答案:

运行时和编译时是指软件程序开发的不同阶段的编程术语。 为了创建一个程序,开发人员首先编写源代码,它定义了程序将如何运行。小程序可能只包含几百行源代码,而大程序可能包含数十万行源代码。源代码必须被编译成机器码才能成为可执行程序。这个编译过程称为编译时。(把编译器看作翻译器)

用户可以打开并运行编译后的程序。当应用程序正在运行时,它被称为运行时。

术语“运行时”和“编译时”经常被程序员用来指代不同类型的错误。编译时错误是一种问题,例如语法错误或缺少文件引用,从而阻止程序成功编译。编译器产生编译时错误,并通常指出源代码的哪一行导致了问题。

如果一个程序的源代码已经被编译成一个可执行程序,那么它在程序运行时可能仍然有错误。例子包括不能工作的特性、意外的程序行为或程序崩溃。这些类型的问题被称为运行时错误,因为它们发生在运行时。

参考

下面是《JAVA编程入门》的作者Daniel Liang关于编译的一段话:

用高级语言编写的程序称为源程序或源代码。因为计算机不能执行源程序,所以源程序必须将翻译转换为执行机器代码。转换可以使用另一种称为解释器或编译器的编程工具来完成。”(Daniel Liang, JAVA程序设计简介, p8)。

...他仍在继续……

编译器将整个源代码转换为机器码文件,然后执行机器代码文件。

当我们输入高级/人类可读的代码时,这在一开始是无用的!它必须被翻译成一个序列的“电子事件”在你的小CPU!实现这一目标的第一步是编译。

简单地说:编译时错误发生在这个阶段,而运行时错误稍后发生。

请记住:仅仅因为一个程序没有错误地编译,并不意味着它将没有错误地运行。

运行时错误将发生在程序生命周期的准备、运行或等待部分,而编译时错误将发生在生命周期的“新”阶段之前。

编译时错误的例子:

语法错误——如果你的代码有歧义,你怎么能把它们编译成机器级指令??你的代码需要100%符合语言的语法规则,否则它不能被编译成工作机器代码

运行时错误的例子:

内存不足——例如,在给定特定程度的变量时,调用递归函数可能会导致堆栈溢出!编译器怎么能预料到这一点!?它不能。

这就是编译时错误和运行时错误的区别

作为其他答案的补充,以下是我对外行的解释:

您的源代码就像一艘船的蓝图。它定义了船应该如何制造。

如果你把你的蓝图交给造船厂,他们在建造船的时候发现了一个缺陷,他们会立即停止建造并向你报告,在船离开干船坞或接触水之前。这是一个编译时错误。这艘船甚至从未真正漂浮过,也没有使用过它的引擎。这个错误之所以被发现,是因为它甚至阻止了这艘船的制造。

当您的代码编译完成时,就像船完成了一样。建好了,可以出发了。当你执行你的代码时,就像在航行中让船下水一样。乘客上了船,引擎在运转船体在水面上,这是运行时间。如果你的船有致命的缺陷,在处女航时就沉没了(或者可能是一些额外的麻烦),那么它就遇到了运行错误。

< >强编译时间: 将源代码转换为机器码并使其成为可执行文件所花费的时间称为编译时间

< >强运行时间: 当一个应用程序正在运行时,它被称为运行时

编译时错误是那些语法错误,缺少文件引用错误。 运行时错误发生在源代码被编译成可执行程序之后,并且程序正在运行时。例如程序崩溃,意外的程序行为或功能不工作

看看这个例子:

public class Test {


public static void main(String[] args) {
int[] x=new int[-5];//compile time no error
System.out.println(x.length);
}}
以上代码编译成功,没有语法错误,完全有效。 但是在运行时,它抛出以下错误
Exception in thread "main" java.lang.NegativeArraySizeException
at Test.main(Test.java:5)
就像在编译时检查了某些情况一样,在运行时检查了某些情况之后,一旦程序满足所有条件,就会得到一个输出。 否则,您将得到编译时或运行时错误

想象你是一个老板,你有一个助理,一个女仆,你给他们一个任务列表,助理(编译时)将抓住这个列表,检查任务是否可以理解,你没有写任何尴尬的语言或语法,所以他知道你想指定某人工作所以他指派他为你,他知道你想要一些咖啡,所以他的角色结束了,女仆(运行时)开始执行这些任务,所以她去给你煮咖啡,但突然她找不到咖啡,所以她停止了煮咖啡,或者她改变了行为,为你煮茶(当程序因为他发现错误而改变行为时)。

public class RuntimeVsCompileTime {


public static void main(String[] args) {
        

//test(new D()); COMPILETIME ERROR
/**
* Compiler knows that B is not an instance of A
*/
test(new B());
}
    

/**
* compiler has no hint whether the actual type is A, B or C
* C c = (C)a; will be checked during runtime
* @param a
*/
public static void test(A a) {
C c = (C)a;//RUNTIME ERROR
}


}


class A{
    

}


class B extends A{
    

}


class C extends A{
    

}


class D{
    

}

您可以通过阅读实际代码来理解代码编译结构。运行时结构并不清楚,除非您了解所使用的模式。