   Compilers and Variables
  Reading about machine code, there are no variables, simply registers and addresses, and you can move information from an address to a register and perform arithmetic and spit that number out to another address and so on.My question is, how does the compiler know what the address of a variable will be?  When I do something as simple as:int x;x = 5;The machine code for that C code must first RESV 4 bytes which we interpret as x, and then MOV the value 5 into the address of x, but in order to move the value 5 into x, there must be some instruction storing the address of x, which means the compiler must somehow know what this address is when it translates the C code into machine code.  How exactly does the compiler do this?  Or does the compiler even do this? 
  One of those registers is our location on the stack, and all the variables in the function we are in are always the same offset from that address.   [edited by - smart_idiot on February 17, 2004 2:13:10 AM];  Could you elaborate or perhaps point me to a site where this issue is discussed in detail?If I have something like this...int x;char y;double z;What I think you''re saying is that there is a register (lets just call it SX) that stores the location of x, and y will be located 4 bytes to the right of x, and z will be located 1 byte to the right of y.So the program always knows the location of z by computing SX + 4 + 1, and the location of y will be SX + 4 and the location of x will be SX.  Perhaps it''s a little more complicated than that but am I atleast on the right track?Assuming I am, this would only then work for sizes that are defined before runtime.What if I had something like...int x;cin >> x;int y[x];double z;How does the program deal with this situation, how does it know the location of z?Thanks for the help. ;quote:Original post by Kranar  Could you elaborate or perhaps point me to a site where this issue is discussed in detail?If I have something like this...int x;char y;double z;What I think you''re saying is that there is a register (lets just call it SX) that stores the location of x, and y will be located 4 bytes to the right of x, and z will be located 1 byte to the right of y.So the program always knows the location of z by computing SX + 4 + 1, and the location of y will be SX + 4 and the location of x will be SX.  Perhaps it''s a little more complicated than that but am I atleast on the right track?Assuming I am, this would only then work for sizes that are defined before runtime.What if I had something like...int x;cin >> x;int y[x];double z;How does the program deal with this situation, how does it know the location of z?Thanks for the help.   The point at which a variable is introduced into code does not necessarily have to be where it shows up on the stack/in registers.  Further, suppose x were not used anymore in the remainder of the function you described.  The register or stack location used to allocate x could be reused to store the value of z.  Compilers play juggling games to allocate variables into stack locations and registers in the most compact way possible.  They do all this juggling so you don''t have to. ;  Being able to write code like you posted is non standard, and as far as I know only works with GCC. The size of an array is required to be known at compile time. I''m not sure how the compiler handles things in that case.I think you got it, but I think generally the first thing at that location would be where to return to when it''s time to exit the function, followed by the arguments to our function, followed by our local variables. ;  <<  Compilers play juggling games to allocate variables into stack locations and registers in the most compact way possible. They do all this juggling so you don''t have to.  >>Oh and I''m greatful that compilers do this juggling for me.  I ask this because I''m working on a fairly primitive scripting language for my game.  I completed the virtual machine and you could technically make subroutines by using the primitive instructions it comes with, but I was hoping to write a compiler to go along with it.  I''ve read a lot on how the C compiler works and how compilers work in general, but none of what I''ve read covers how compilers handle variables.Thanks again. ;quote:int x;cin >> x;int y[x];double z;There are two ways the compiler could implement the above:The first, and probably the most likely, is to calculate the location of z every time it''s accessed, thus: address of z = address of y + x * sizeof (int). The compiler will certainly use an extra variable, x'' say, that holds the value of x at the point where the array is declared, such that any changes in the value of x further down the code doesn''t affect the addressing of z. Note then that:double z;int y [x];  would produce more optimised code as the address of z is always known. However, modern compilers would probably do this reording for you (you can always check by looking at an assembly listing, -save-temps option for GCC allows you to do this).The second method is to treat the code like this:int *y = malloc (sizeof (int) * x);double z;  Here, the address of z is always the same regardless of x. This is unlikely to happen as new can return null (equivalent to running out of stack space I guess) and it can produce unexpected memory fragmentation. When y goes out of scope, the memory allocated would be freed. In C++, I''m not sure what the standard says about allocating arrays and the initialisation thereof, so new/delete may be called instead of malloc/free.Skizz ;  In the case of an if, what would happen? int x = 3;if(someCondition) {  int y = 5;  cout << y << end;} else {  int z = x + 2;  cout << z << endl;}Those variables y and z, may or may not ever be declared, if one of them is, it would change the offset when locating any variables declared later on. ;  In this case, the compiler will probably allocate the same address to Y and Z since their scopes are mutually exclusive (a good optimiser will see that Y and Z don''t change and just put the constants into the function calls directly and not actually assign a memory address to either). In a debug build, the compiler may extend the stack frame within each of the if-else statements.Skizz 