If somewhere in my code, I use the address of a variable (pass it to some other function, for example), the compiler will automatically choose to store it in memory? (as opposed to the possibility of storing it in a register).
Otherwise, what happens if I ask for the address of a variable like that (stored as register)? I know we can't take the address of variables explicitly set to register (register int c
).
EDIT:
For example, if i do something like
int c = 1;
print("Address of c: %p", &c);
Then this variable couldn't be stored in a register, could it? The compiler would automatically set it as stored in memory? Otherwise (if it is just stored in a register), what would be the address shown in the screen?
A register does not have an address. Therefore, you cannot apply the address operator ( & ) to a register variable. You cannot use the register storage class specifier when declaring objects in namespace scope.
Register variables tell the compiler to store the variable in CPU register instead of memory. Frequently used variables are kept in registers and they have faster accessibility. We can never get the addresses of these variables.
Register variables are stored in registers. Static variable is stored in the memory of the data segment. In register variables, CPU itself stores the data and access quickly.
A pointer is a type of variable that stores as its data a memory address which may or may not be a memory address of a variable declared in your program.
First, the C Standard prohibits taking the address of a variable that is declared register
, just as it does for bit fields in struct
s.
For non-register ("auto") variables, the short answer is yes. The simplest strategy of an optimizer is to immediately spill variables whose addresses are taken.
"Spill" is just a term from the literature of register allocation meaning "decide to place in memory rather than a register."
A sophisticated optimizer can do an alias analysis and still hold a value in a register, even though its address has been taken. This is possible wherever it can be proven that the resulting pointer can't possibly be used to change the value.
Another relevant optimization is live range splitting. This allows a variable to be stored in a register for part of the range of instructions where it's holding a useful value (its "live range") and to be spilled in other parts. In this case the spilled parts would correspond to places where the pointer might be used to change the variable's value. For example:
x = 3;
... lots of computations involving x
if T {
// SPILL HERE, so store register holding x to memory
int *p = &x;
... lots of computations, perhaps using p to change x
*p = 2;
// DONE SPILL HERE, so reload register
... more code here not using p to change x.
}
else {
... lots of computations involving x.
}
An aggressive optimizer of this code might allocate a stack position for x, but load it into a register at the top of the code, maintaining it there except for the region marked as a SPILL. This region would be surrounded by a store of the register to memory and a matching register load.
By taking its address, you force the compiler to put the variable in memory and not to to optimize it into a register.
This answer has some good info: Address of register variable
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With