views:

153

answers:

4

Say that I have a C program and it has this line:

int a = 12;

Is the value of 12 bound to 'a' during compile time? Or is the value placed into memory during run time when the scope of the program hits 'a'?

What about programming languages like Python and 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.

+2  A: 

The value 12 is not statically bound to a. Rather, a is bound to a memory location, which is initialized to the value 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.

Fred Larson
Nick T
@Nick T: See my edit.
Fred Larson
+1  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). In regular Ruby, it may do something like this as well. In Jython and JRuby, they will definitely optimize the same way durning the JIT process.

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.

Zac Bowling
+8  A: 

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; 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.

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. (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.)

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.

If you take a reference to a, a la int *aptr = &a;, then the language specification says that a must have a location in memory (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.

In other languages there are obviously other specifications. Technically, in dynamic languages the compiler can perform similar optimizations. If you have a Python function:

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). Traditionally, Python implementations have no such optimizations because its language philosophy mandates debuggability, VM implementation simplicity, and programmer comprehension above optimizations.

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. 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.

Supporting debuggers is hard, let's go optimizing!

cdleary
+1 for detail and interesting information about other languages.
R..
A: 

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 (e.g. declaring a in a recursive function). 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.

tia