rajesh20k
August 6th, 2005, 12:20 AM
hi,
Can I take or compute tahe address of register variable?
can I make register variable as global or static?
Please let me know reason.
Dave McLelland
August 6th, 2005, 03:55 PM
You cannot take the address of a register variable, because a register does not have an address. A register is inside the processor chip, not in memory.
I dont know about a static or global register variable.
The register keyword only provides a hint to the compiler. The compiler does not have to honour the request. The Microsoft C/C++ compiler does not honor user requests for register variables.
NoHero
August 6th, 2005, 05:33 PM
Can I take or compute tahe address of register variable?
As stated above, a register variable is in an internal CPU register which doesn't have an address at all.
can I make register variable as global or static?
Of course you can. But you won't get what you are expacting because the type specifier "register" is - as for example "inline" too - just a hint to the compiler to make this optimation. He is not forced to keep your variable in the register. If you make it global it has to be in a register the entire time, but those are also used for other things. For example dividing and multiplying operations require two registers. The compiler won't be able to keep this variable in the registers. The same with it would be static.
Register variables are used for "for" loops, in this case they can achieve an speed boost:
// A is some array with A_SIZE as size
for ( register int iIndex = 0; i < A_SIZE; ++i )
{
A[iIndex] += (iIndex * 2);
}
Note that multiplications or divisions with or on the register variable might effect the register specifier, because of usage of certain registers on the x86.
Best Regards,
Florian
SuperKoko
August 6th, 2005, 06:08 PM
I suppose that register variable declarations are ignored by modern compilers who choose wisely how and when a variable must be put in a register.
But, for sure if you take the address of a local variable, it must absolutely have an address, so the variable is allocated on the stack. But in many cases the compiler may temporary load the local variable value from the stack to a register and use this value for a time (except if the variable is declared as volatile, in that case the compiler knows that the value on the stack may change at any time).
void f()
{
int i;
// some code here which use i (and not its address), so the compiler can put i in a register.
g(&i); // use address of i
for(i=0;i<1000;++i)
{
// a loop which does not call any function and does not use the address of i, so the compiler knows that in this code block i is not modified or only modified explicitly, so he can put i in a register during the whole loop.
}
h(); // calls an externally-linked function, so the compiler must 'store' the value of i, moving it from the register to the stack, so if h uses a pointer to i, the pointed value will be correct.
}
So, in fact the compiler may put temporary the variable in a register.
But if the variable address is used somewhere, there must be some memory allocated on the stack for this variable.
global variables and static variables may be 'optimized' they are not modified (typically const variable), and their address is never used, that is, their values may be replaced by literal (immediates) values in the assembly code.
This type of optimization is more likely to occur if the variable is an integral or pointer type, but may occur even with big objects.
For internal-linked global variables and static variables this optimization occur at compile-time, and if the variable addresses is never used the compiler may not generate any data in the data section of the object file (.obj) generated by the compilation stage.
For externally linked global variables, if only the module which defined the global variable use it and this variable is optimized in this module, the variable symbol may be removed at link time (that is, don't appear in the data section of the executable file).
If more than one module use it, the variable must have an address, and is defined in the data section, and this variable can only be optimized in the module which defined it, because in this module the variable value is known at compile time, so the compiler can use it as a literal value. But the variable must be explicitly defined as const, because the compiler cannot know in the defining module if there are other modules which modify the variable, except if const is explicitly specified.
If the variable is modified (so it is not const), the compiler cannot optimize it, that is cannot replace its value by a literal.
But in all cases, if the variable is not const, the compiler may load the variable (or one of its part if it is a structure), temporary, in a register.
The compiler must just be sure that between the 'load in register' and 'store to memory' instructions, the variable is not modified externally, that is in another function that the function which is currently using the variable in a register. This problem is similar to the problem of local variables, but the compiler must know that from the start to the end of the function, all other externally-linked functions may change the value of the global variable (with local variable, the compiler must assume that, only for statements following the first statement which pass the address of the local variable to a foreign function).
To simplify:
global variables may be replaced by literal values if:
They are declared as const (preferable)
or are:
Locally-linked, that is declared as static at the module level
Not modified at any position in the module
Their address is not taken, or at least the compiler must trace that their value may not be known by externally-linked functions or functions which may modify the value of the variable using this address.
global variables may always be put in registers temporary, for a short or long time, if, and only if they are not declared as volatile.
If a variable is volatile, its value may be put into a register (because it is the only way to work on values on x86 architectures), but only for a very short time, that is, the compiler may not optimize multiple loads of a volatile variable to one load.
But for sure a global variable cannot be a 'register' as register variables were with very old compilers. That is in the same register for all its lifetime, because its lifetime is the lifetime of the whole program. So that should mean a register occupied from the start to the end of program, what cannot be done for external linkage reasons (and speed reasons... registers are very precious).
Note that, since literal values may use much code space, they can be temporary loaded into registers, that is:
const int i=-1; // global const variable.
int f()
{
// some code here
j=i;
k=i;
// some other code here
}
It will probably generate this assembly code:
mov eax,-1
mov [j],eax
mov [k],eax
Instead of:
mov [j],-1
mov [k],-1
Or even it may generate this (if size optimization flags are activated):
xor eax,eax
dec eax
mov [j],eax
mov [k],eax
But, of course it depends on the compiler and optimization flags (optimizing for size vs speed).