简体   繁体   English

这是静态绑定的吗?

[英]Is this statically bound?

Say that I have a C program and it has this line: 假设我有一个C程序,它包含以下内容:

int a = 12;

Is the value of 12 bound to 'a' during compile time? 编译期间12的值是否绑定到'a'? Or is the value placed into memory during run time when the scope of the program hits 'a'? 还是当程序范围达到“ a”时在运行时将该值放入内存?

What about programming languages like Python and Ruby? 像Python和Ruby这样的编程语言呢?

Are there languages/instances where a value is statically bound to a variable? 是否存在将值静态绑定到变量的语言/实例? I've been thinking about this for a while now and I honestly can't think of a logical reason for statically binding a value to a primitive type. 我已经考虑了一段时间了,老实说,我想不出将值静态绑定到原始类型的逻辑原因。

Compilers and virtual machines effectively "implement" programming languages. 编译器和虚拟机有效地“实​​现”了编程语言。 They only have to do what is specified by the language semantics and observable for a given program in order to be correct. 他们只需要执行语言语义所指定的操作,并且对于给定的程序即可观察到正确的内容。

When you write the definition statement int a = 12; 当您编写定义语句时, int a = 12; in a C program, you are informing the compiler that there is a variable named a whose initial value is set to the constant literal twelve. 在C程序中,您正在通知编译器有一个名为a的变量,其初始值设置为常量文字12。

If you never observe a , the compiler can completely get rid of it, because you can't tell the difference during program execution per the language specification. 如果您从未观察到a ,则编译器可以完全摆脱它,因为您无法根据语言规范分辨出程序执行期间的区别。 (For example, if you were to pause the program and scan the stack at that point, the value 12 need not be there at all. Its necessity for being on the machine stack is not part of the language specification.) (例如,如果您要暂停程序并在那时扫描堆栈,则值12根本不需要在那里。其在机器堆栈上的必要性不是语言规范的一部分。)

If you observe a but find that it's impossible for your program to mutate its value, the compiler has inferred that it is actually static const and can perform an optimization called "constant propagation" to push a hard-coded twelve into the dependent instructions. 如果您观察到a但发现您的程序无法更改其值,则编译器已推断出它实际上是static const并且可以执行称为“恒定传播”的优化,以将硬编码的十二个推入从属指令。

If you take a reference to a , a la int *aptr = &a; 如果您引用a ,则la int *aptr = &a; , then the language specification says that a must have a location in memory (IIRC). ,然后语言规范说a 必须在内存(IIRC)中有位置。 This means that, per the specification, there will be a valid, int-sized slot in memory (on the stack, in any reasonable implementation) that will contain 12. 这意味着,按照规范,内存中(在堆栈中,以任何合理的实现方式)将有一个有效的,以int大小为单位的插槽,其中将包含12。

In other languages there are obviously other specifications. 在其他语言中,显然还有其他规范。 Technically, in dynamic languages the compiler can perform similar optimizations. 从技术上讲,使用动态语言,编译器可以执行类似的优化。 If you have a Python function: 如果您具有Python函数:

def do_nothing():
    a = 12

You could imagine that the Python compiler, which turns the language text into bytecodes, might choose to omit the body of that function entirely (for pedants: except the implicit return None ). 您可以想象,将语言文本转换为字节码的Python编译器可能会选择完全忽略该函数的主体(对于pedants:除了隐式return None )。 Traditionally, Python implementations have no such optimizations because its language philosophy mandates debuggability, VM implementation simplicity, and programmer comprehension above optimizations. 传统上,Python实现没有这样的优化,因为它的语言理念要求调试性,VM实现的简单性以及对优化的程序员理解。

There are also some tricky constructs in dynamic languages that make inference more difficult. 动态语言中还存在一些棘手的构造,这些构造使推理更加困难。 For example, Python allows a great deal of code object inspection that is expected to work across implementations. 例如,Python允许大量代码对象检查,这些检查可望在各种实现中使用。 Acquiring/inspecting stack traces and the local arguments of activated frames requires at least slow-path fallback mechanisms, which increase optimization complexity significantly. 获取/检查堆栈跟踪和已激活帧的局部参数至少需要慢速路径回退机制,这会显着增加优化的复杂性。 We're ditching support for some of these kinds of language-level-runtime-stack-inspection things in JavaScript with ECMAScript revision 5. 在ECMAScript版本5中,我们放弃了对JavaScript中某些此类语言级别的运行时堆栈检查的支持。

Supporting debuggers is hard, let's go optimizing! 支持调试器很困难,让我们开始优化吧!

The value 12 is not statically bound to a . 的值12没有静态绑定a Rather, a is bound to a memory location, which is initialized to the value 12. 而是,将a绑定到一个存储位置,该存储位置被初始化为值12。

If a were declared as const and nothing ever took the address of it, the compiler would not need to allocate storage and may use it as a compile-time constant, in which case the value 12 would be statically bound to a . 如果将a声明为const而没有任何东西占用其地址,则编译器将不需要分配存储,而可以将其用作编译时常量,在这种情况下,值12将静态绑定到a

It really depends on the context of the variables use and the compiler optimizations you have enabled. 这实际上取决于变量使用的上下文以及您启用的编译器优化。 If the variable is never updated and used in a small enough scope, its likely to be compiled out in the final output, even in the lightest of optimizations. 如果该变量从未更新过并在足够小的范围内使用,则即使在最优化的情况下,也很可能在最终输出中将其编译出来。 If compiler detects the variable is passed around or updated later (or potentially updated later) it may load the integer on to the stack. 如果编译器检测到该变量被传递或稍后更新(或稍后可能更新),则可能会将整数加载到堆栈上。 This is dependent on the architecture but if its only updated a short time later and then disposed, it may load it into a register if it can and work with it there. 这取决于体系结构,但是如果仅在短时间后进行更新然后处理,则可以将其加载到寄存器中并在其中使用。

In CPython, it can do similar optimizations in some cases if it can scope the variable (unless its global, then it will be loaded in the heap). 在CPython中,如果可以确定变量的范围,它在某些情况下可以进行类似的优化(除非它是全局变量,否则它将被装入堆中)。 In regular Ruby, it may do something like this as well. 在常规Ruby中,它也可能会执行类似的操作。 In Jython and JRuby, they will definitely optimize the same way durning the JIT process. 在Jython和JRuby中,他们肯定会优化JIT流程的相同方式。

I'm not a complete expert, as I've only written very basic compilers that output to bytecode to be JITed later and that was years ago. 我不是一个完整的专家,因为我只写了非常基本的编译器,这些编译器输出到字节码,以便在以后和几年前进行JIT。

I think a cannot be statically bound, because a is not a constant and that means there might be more than one value of a at the same time (eg declaring a in a recursive function). 我认为, a不能静态绑定,因为a不是恒定的,这意味着有可能是多个值a在同一时间(例如宣布a在递归函数)。 It is important that each value of a must have separated address in the memory, which implies that a cannot be statically bound to a specific single memory address. 重要的是, a每个值必须在内存中具有单独的地址,这意味着a不能静态绑定到特定的单个内存地址。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM