C中存储的指针地址在哪里? [英] Where are addresses of pointers stored in C?

查看:66
本文介绍了C中存储的指针地址在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习 C,目前正在学习指针.我理解的原理是将一个字节的地址作为变量存储在内存中,这样就可以从内存中获取字节并写入内存地址.

I'm learning C and currently learn about pointers. I understand the principle of storing the address of a byte in memory as a variable, which makes it possible to get the byte from memory and write to the memory address.

但是,我不明白指针的地址存储在哪里.假设一个指针的值(内存中一个字节的地址)存储在内存中的某处——程序如何知道指针存储在哪里?难道这不需要一个指向指针的指针,从而导致无穷无尽的指向指针的指针......?

However, I don't understand where the address of a pointer is stored. Let's say the value of a pointer (the address of a byte in memory) is stored somewhere in memory - how can the program know where the pointer is stored? Wouldn't that need a pointer for a pointer resulting in endless pointers for pointers for pointers... ?

更新

实际问题是:编译器如何为变量分配内存地址".我发现 this question 指出了这个主题.

The actual question is: "How does the compiler assign memory addresses to variables". And I found this question which points out this topic.

感谢所有回答的人.

推荐答案

这是一个实现细节,但是...

This is an implementation detail, but...

并非所有地址都存储在内存中.处理器还具有寄存器,可用于存储地址.与您可以在内存中存储的数十亿字节相比,只有少数几个寄存器可以以这种方式使用,可能是 16 或 32 个.

Not all addresses are stored in memory. The processor also has registers, which can be used to store addresses. There are only a handful of registers which can be used this way, maybe 16 or 32, compared to the billions of bytes you can store in memory.

有些变量会存储在寄存器中.例如,如果您需要快速将一些数字相加,编译器可能会使用例如 %eax(x86 上的寄存器)来累加结果.如果启用优化,变量只存在于寄存器中是很常见的.当然,在任何给定时间只有少数变量可以在寄存器中,因此大多数变量需要在某个时刻写入内存.

Some variables will get stored in registers. If you need to quickly add up some numbers, for example, the compiler might use, e.g., %eax (which is a register on x86) to accumulate the result. If optimizations are enabled, it is quite common for variables to exist only in registers. Of course, only a few variables can be in registers at any given time, so most variables will need to get written to memory at some point.

如果一个变量因为没有足够的寄存器而被保存到内存中,它被称为溢出".编译器非常努力地避免寄存器溢出.

If a variable is saved to memory because there aren't enough registers, it is called "spilling". Compilers work very hard to avoid register spilling.

int func()
{
    int x = 3;
    return x;
    // x will probably just be stored in %eax, instead of memory
}

栈上的变量

通常,一个寄存器指向一个称为堆栈"的特殊区域.所以一个函数使用的指针可能会存储在堆栈中,通过对堆栈指针进行指针运算,可以计算出该指针的地址.堆栈指针没有地址,因为它是一个寄存器,而寄存器没有地址.

Variables on the stack

Commonly, one register points to a special region called the "stack". So a pointer used by a function may be stored on the stack, and the address of that pointer can be calculated by doing pointer arithmetic on the stack pointer. The stack pointer doesn't have an address because it's a register, and registers don't have addresses.

void func()
{
    int x = 3; // address could be "stack pointer + 8" or something like that
}

编译器选择堆栈的布局,为每个函数提供一个足够大的堆栈框架",以容纳该函数的所有变量.如果优化被禁用,变量通常会在堆栈帧中获得自己的位置.启用优化后,槽将被重用、共享或完全优化.

The compiler chooses the layout of the stack, giving each function a "stack frame" large enough to hold all of that function's variables. If optimization is disabled, variables will usually each get their own slot in the stack frame. With optimization enabled, slots will be reused, shared, or optimized out altogether.

另一种选择是将数据存储在固定位置,例如地址 100".

Another alternative is to store data at a fixed location, e.g., "address 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
}

这实际上并不少见.请记住,地址 100"不一定对应于 RAM——它实际上是一个虚拟地址,指的是您程序的虚拟地址空间的一部分.虚拟内存允许多个程序都使用地址 100",并且该地址将对应每个运行程序中不同的物理内存块.

This is actually not uncommon. Remember, that "address 100" doesn't correspond to RAM, necessarily—it is actually a virtual address referring to part of your program's virtual address space. Virtual memory allows multiple programs to all use "address 100", and that address will correspond to a different chunk of physical memory in each running program.

绝对地址也可用于没有虚拟内存的系统,或用于不使用虚拟内存的程序:引导加载程序、操作系统内核和嵌入式系统软件可能使用没有虚拟内存的固定地址.

Absolute addresses can also be used on systems without virtual memory, or for programs which don't use virtual memory: bootloaders, operating system kernels, and software for embedded systems may use fixed addresses without virtual memory.

编译器通过在机器代码中放置一个洞"来指定绝对地址,称为重定位.

An absolute address is specified by the compiler by putting a "hole" in the machine code, called a relocation.

int get_x()
{
    return x; // returns the contents of address ???
              // Relocation: please put the address of "x" here
}

然后链接器选择 x 的地址,并将地址放入 get_x() 的机器码中.

The linker then chooses the address for x, and places the address in the machine code for get_x().

另一种选择是将数据存储在与正在执行的代码相关的位置.

Yet another alternative is to store data at a location relative to the code that's being executed.

// 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
}

共享库几乎总是使用这种技术,它允许在程序地址空间中的任何可用地址加载共享库.与程序不同,共享库不能选择它们的地址,因为另一个共享库可能选择相同地址.程序也可以使用这种技术,这被称为与位置无关的可执行文件".程序将在缺少虚拟内存的系统上与位置无关,或者在具有虚拟内存的系统上提供额外的安全性,因为它使编写 shell 代码变得更加困难.

Shared libraries almost always use this technique, which allows the shared library to be loaded at whatever address is available in a program's address space. Unlike programs, shared libraries can't pick their address, because another shared library might pick the same address. Programs can also use this technique, and this is called a "position-independent executable". Programs will be position-independent on systems which lack virtual memory, or to provide additional security on systems with virtual memory, since it makes it harder to write shell code.

就像绝对地址一样,编译器会在机器代码中放置一个洞"并要求链接器填写.

Just like with absolute addresses, the compiler will put a "hole" in the machine code and ask the linker to fill it in.

int get_x()
{
    return x; // return the contents of here + ???
              // Relocation: put the relative address of x here
}

这篇关于C中存储的指针地址在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆