8

How is scope of a variable is implemented by compilers? I mean, when we say static variable, the scope is limited to the block or functions that defined in the same file where the static variable is defined? How is this achieved in machine level or at memory level?

How actually is this restriction achieved?

How is this scoping resolved at program run time?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
vijay kumar
  • 81
  • 1
  • 3
  • Check this out:- http://stackoverflow.com/questions/898432/how-is-static-variable-initialization-implemented-by-the-compiler – Rahul Tripathi Nov 02 '12 at 16:59

3 Answers3

8

It is not achieved at all at the machine level. The compiler checks for scopes before machine code is actually generated. The rules of C are implemented by the compiler, not by the machine. The compiler must check those rules, the machine does not and cannot.

A very simplistic explanation of how the compiler checks this:

Whenever a scope is introduced, the compiler gives it a name and puts it in a structure (a tree) that makes it easy to determine the position of that scope in relation to other scopes, and it is marked as being the current scope. When a variable is declared, its assigned to the current scope. When accessing a variable, it is looked for in the current scope. If not found, the tree is looked up to find the scope above the current one. This continues until we reach the topmost scope. If the variable is still not found, then we have a scope violation.

Nikos C.
  • 50,738
  • 9
  • 71
  • 96
1

inside compilers, its implementation defined. For example if I were writing a compiler, I would use a tree to define 'scope' and it would definitely be a symbol table inside a binary tree.

Some would use an arbitrary depth Hash table. Its all implementation defined.

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
0

I'm not 100% sure I understand what you are asking, but if you mean "how are static variables and functions stored in the final program", that is implementation-defined.

That said, a common way of storing such variables and functions is in the same place as any other global symbols (and some non-global ones) -- the difference is that these are not "exported", and thus not visible in any outside code trying to link to our software.

In other words, a program which has the following in it:

int var;
static int svar;
int func() { static int func_static; ... }
static int sfunc() { ... }

... might have the following layout in memory (let's say our data starts at 0xF000 and functions at 0xFF00):

0xF000: var
0xF004: svar
0xF008: func.func_static
...
0xFF00: func's data
0xFF40: sfunc's data /* assuming we needed 0x40 bytes for `func`! */

The list of exports, however, would only contain the non-static symbols, aka the exported ones:

var   v 0xF000
func  f 0xFF00

Again -- note how, while the static data is still written into the files (it has to be stored somewhere!), it is not exported; in layman's terms, our program does not tell anyone that it contains svar, sfunc and similar.

In Unices, you can list the symbols that a library or a program exports with the nm tool: http://unixhelp.ed.ac.uk/CGI/man-cgi?nm ; there do exist similar tools for Windows (GnuWin32 might have something similar).

In practice, executable code is often stored separately from the data (so that it can be protected from writes, for example), and it both may get reordered to minimize memory use and cache misses, but the idea remains the same.

Of course, optimizations can be applied -- for example, a static function could be inlined in its every invokation, meaning that no code is generated for the function itself at all, and thus it does not exist on its own anywhere.

Tim Čas
  • 10,501
  • 3
  • 26
  • 32