-->

如何存储在内存中的变量名使用C?如何存储在内存中的变量名使用C?(How are variable

2019-05-13 00:28发布

在C语言中,假设你有一个变量叫variable_name 。 比方说,它位于0xaaaaaaaa ,在内存地址,你有整数123.因此,换句话说, variable_name中包含123。

我在寻找澄清周围的措辞“ variable_name位于0xaaaaaaaa ”。 编译器如何识别字符串“变量名”与特定的存储地址相关联? 是字符串“变量名”的地方存储在内存中? 该编译器刚刚替补variable_name0xaaaaaaaa每当看到它,如果是这样,是不是必须使用的内存,以使该替换吗?

Answer 1:

变量名不编译运行(除非特殊情况下,像在共享库或调试符号导出全局)后不复存在。 编译整个行动旨在通过采取源代码所代表的那些符号名和算法,并将其转化为本机指令。 所以,是的,如果你有一个全局variable_name ,以及编译器和连接决定把它在0xaaaaaaaa ,那么无论它在代码中被使用,它只是可以通过该地址进行访问。

因此,要回答你的问题的文字:

编译器如何识别字符串“变量名”与特定的存储地址相关联?

工具链(编译器&接头)共同指定的存储器位置的变量。 这是编译器的工作是让所有引用的轨道,后来把连接在正确的地址。

是字符串"variable_name"某处存储在内存中?

只有当编译运行。

该编译器刚刚替补variable_name0xaaaaaaaa每当看到它,如果是这样,是不是必须使用的内存,以使该替换吗?

是的,这几乎是发生了什么,除了这两个阶段的工作与连接。 是的,它使用的内存,但它的编译器的内存,在运行时为你的程序没有什么。

一个例子可以帮助你理解。 让我们来尝试一下这个方案:

int x = 12;

int main(void)
{
    return x;
}

很简单,对不对? 好。 让我们这个节目,并编译它,并期待在拆卸:

$ cc -Wall -Werror -Wextra -O3    example.c   -o example
$ otool -tV example
example:
(__TEXT,__text) section
_main:
0000000100000f60    pushq   %rbp
0000000100000f61    movq    %rsp,%rbp
0000000100000f64    movl    0x00000096(%rip),%eax
0000000100000f6a    popq    %rbp
0000000100000f6b    ret

看到movl线? 它抓住了全局变量(在指令指针相对的方式,在这种情况下)。 没有更多的提x

现在,让我们把它有点复杂,并添加一个局部变量:

int x = 12;

int main(void)
{  
    volatile int y = 4;
    return x + y;
}

该方案的拆卸是:

(__TEXT,__text) section
_main:
0000000100000f60    pushq   %rbp
0000000100000f61    movq    %rsp,%rbp
0000000100000f64    movl    $0x00000004,0xfc(%rbp)
0000000100000f6b    movl    0x0000008f(%rip),%eax
0000000100000f71    addl    0xfc(%rbp),%eax
0000000100000f74    popq    %rbp
0000000100000f75    ret

现在有两个movl指令和addl指令。 你可以看到,第一movl正在初始化y ,其中它的决定将是在栈(基指针- 4)。 那么接下来movl得到全球x到寄存器eaxaddl增加y到该值。 但正如你所看到的,字面xy字符串不存在了。 他们对来说,程序员的便利,但电脑肯定不能在执行时关心他们。



Answer 2:

C编译器首先创建一个符号表,用于存储变量名,它位于哪里的记忆之间的关系。 编译时,它使用此表特定内存位置替换变量的所有实例,正如其他人说。 你可以在它身上找到了更多的维基百科页面上。



Answer 3:

所有变量是由编译器取代。 首先,他们取代有引用后来链接器将代替引用地址。

换一种说法。 变量名不再可用,一旦编译器通过运行



Answer 4:

这就是所谓的一个实现细节 。 虽然你的描述是我用过所有的编译器的情况下,它并不需要如此。 C编译器可以把每一个变量在哈希表中,并看看他们在运行时(或类似的东西),实际上早JavaScript解释器确实做到了(现在,他们做即时编译导致一些更原始。)

具体地,对于像VC ++,GCC,和LLVM共同编译器:编译器将通常一个变量分配给在存储器中的位置。 的全局或静态变量的范围得到了程序运行时不改变一个固定的地址,而函数内的变量进行堆栈地址,也就是说,相对于当前栈指针,它的每一次变化的函数是一个地址调用。 (这是一个过于简单化。)堆栈地址无效尽快函数返回,但有有有效的零开销使用的效益。

一旦一个变量分配给它的地址,没有为变量的名称不再需要,所以它被丢弃。 根据样的名字,这个名字可以在预处理时间(宏名),编译时间(静态和局部变量/函数),并链接时被丢弃(全局变量/函数)。如果一个符号被导出(可见于其他程序,使他们能够访问它),这个名字通常会在占用的内存和磁盘空间量微不足道“符号表”保持地方。



Answer 5:

该编译器刚刚替补变量名称为0xaaaaaaaa,只要自己认为它

是。

如果是的话,那岂不是要使用的内存,以使该替换吗?

是。 但它的编译器,后编译你的代码,你为什么要在乎的记忆?



文章来源: How are variable names stored in memory in C?