Min*_*ock 4 c memory variables pointers memory-address
我正在学习C并且目前正在学习指针.我理解将一个字节的地址存储在内存中作为变量的原理,这使得从内存中获取字节并写入内存地址成为可能.
但是,我不明白指针的地址存储在何处.假设一个指针的值(内存中一个字节的地址)存储在内存中 - 程序如何知道指针的存储位置?难道不需要指针指针导致指针指针无穷无尽的指针......?
UPDATE
实际问题是:"编译器如何为变量分配内存地址".我发现这个问题指出了这个话题.
感谢所有回答的人.
这是一个实现细节,但......
并非所有地址都存储在内存中.处理器还有寄存器,可用于存储地址.只有少数几个寄存器可以这种方式使用,可能是16或32,与你可以存储在内存中的数十亿字节相比.
一些变量将存储在寄存器中.例如,如果需要快速添加一些数字,编译器可能会使用(例如,%eaxx86上的寄存器)来累积结果.如果启用了优化,则变量仅存在于寄存器中是很常见的.当然,在任何给定时间只有少数变量可以在寄存器中,因此大多数变量需要在某个时刻写入存储器.
如果由于没有足够的寄存器将变量保存到存储器,则称为"溢出".编译器非常努力地避免寄存器溢出.
int func()
{
int x = 3;
return x;
// x will probably just be stored in %eax, instead of memory
}
Run Code Online (Sandbox Code Playgroud)
通常,一个寄存器指向称为"堆栈"的特殊区域.因此,函数使用的指针可以存储在堆栈中,并且可以通过对堆栈指针执行指针运算来计算该指针的地址.堆栈指针没有地址,因为它是寄存器,寄存器没有地址.
void func()
{
int x = 3; // address could be "stack pointer + 8" or something like that
}
Run Code Online (Sandbox Code Playgroud)
编译器选择堆栈的布局,为每个函数提供一个足够大的"堆栈帧"来容纳所有函数的变量.如果禁用优化,变量通常会在堆栈帧中获得自己的插槽.启用优化后,将重新使用,共享或优化插槽.
另一种替代方案是将数据存储在固定位置,例如"地址100".
// global variable... could be stored at a fixed location, such as address 100
int x = 3;
int get_x()
{
return x; // returns the contents of address 100
}
Run Code Online (Sandbox Code Playgroud)
这实际上并不罕见.请记住,"地址100"不符合RAM,必然,它实际上是一个虚拟地址指的是你的程序的一部分虚拟地址空间.虚拟内存允许多个程序全部使用"地址100",并且该地址将对应于每个运行程序中的不同块物理内存.
绝对地址也可用于没有虚拟内存的系统,或者用于不使用虚拟内存的程序:引导加载程序,操作系统内核和嵌入式系统软件可以使用没有虚拟内存的固定地址.
绝对地址由编译器通过在机器代码中放置一个"空洞"来指定,称为重定位.
int get_x()
{
return x; // returns the contents of address ???
// Relocation: please put the address of "x" here
}
Run Code Online (Sandbox Code Playgroud)
然后链接器选择地址x,并将地址放在机器代码中get_x().
另一种替代方案是将数据存储在相对于正在执行的代码的位置.
// global variable... could be stored at address 100
int x = 3;
int get_x()
{
// this instruction might appear at address 75
return x; // returns the contents of this address + 25
}
Run Code Online (Sandbox Code Playgroud)
共享库几乎总是使用这种技术,它允许在程序的地址空间中可用的任何地址加载共享库.与程序不同,共享库无法选择其地址,因为另一个共享库可能选择相同的地址.程序也可以使用这种技术,这称为"位置无关的可执行文件".程序将独立于缺乏虚拟内存的系统,或者在具有虚拟内存的系统上提供额外的安全性,因为它使得编写shell代码变得更加困难.
就像使用绝对地址一样,编译器会在机器代码中放置一个"漏洞"并要求链接器填写它.
int get_x()
{
return x; // return the contents of here + ???
// Relocation: put the relative address of x here
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3139 次 |
| 最近记录: |