C ++如何在内存中访问变量?

时间:2016-02-03 11:28:48

标签: c++ memory

当我在C ++程序中创建一个新变量时,例如char:

1.) In PHP, its automatically convert Type Casting.
2.) Rules of Type Casting : 
    2.1) int + int = int
    2.2) string + string = string
    2.3) float + float = double
    2.4) int + string = int     
    2.5) float + string = double
    2.6) int + float = double

C ++如何在内存中访问此变量?我想象它需要存储变量的内存位置,但那需要一个指针变量,并且需要再次访问该指针。

5 个答案:

答案 0 :(得分:3)

请参阅docs

  

声明变量时,存储其值所需的内存为   在内存中分配了一个特定的位置(其内存地址)。   通常,C ++程序不会主动确定确切的内存   存储变量的地址。幸运的是,那个任务是   离开程序运行的环境 - 通常是一个   决定特定内存位置的操作系统   运行。但是,程序能够获得它可能是有用的   运行时期间变量的地址,以便访问数据单元格   相对于它的某个位置。

您还可以在Variables and Memory

上查阅此文章
  

筹码

     

堆栈是局部变量和函数参数所在的位置。它   被称为堆栈,因为它遵循后进先出原则。   随着数据被添加或推送到堆栈,它会增长,并且当数据增加时   删除或弹出它缩小。实际上,内存地址不是   每次推送或弹出数据时,物理移动   堆栈,而不是堆栈指针,顾名思义指向   堆栈顶部的内存地址,上下移动。   这个地址以下的所有内容都被认为是在堆栈上   可用,而它上面的所有东西都不在堆栈中,并且无效。   这一切都是由操作系统自动完成的   结果它有时也称为自动记忆。在   非常罕见的情况,一个人需要能够明确   调用这种类型的内存,可以使用C ++关键字auto。   通常,会在堆栈上声明变量,如下所示:

void func () { 
int i; float x[100];

...

}
     

在堆栈上声明的变量仅在   他们的声明范围。这意味着当列出函数func()时   以上返回,i和x将不再可访问或有效。

     

放置在堆栈上的变量还有另一个限制:   操作系统只分配一定的空间   堆。正在执行的程序的每个部分都会进入   范围,操作系统分配适当的内存量   这是将所有局部变量保存在堆栈上所必需的。如果这   大于操作系统允许的内存量   堆栈的总大小,然后程序将崩溃。虽然   有时可以通过编译时改变堆栈的最大大小   参数,它通常相当小,远远不及总数   机器上可用的RAM量。

答案 1 :(得分:2)

C ++本身(或编译器)可以根据程序结构访问此变量,表示为数据结构。也许你问的是程序中的其他部分如何在运行时访问它。

答案是它有所不同。它可以存储在寄存器,堆栈,堆上或data / bss部分(全局/静态变量)中,具体取决于它的上下文和为其编译的平台:如果需要传递它通过引用(或指针)到其他函数,它可能会存储在堆栈中。如果您只需要在函数的上下文中,它可能会在寄存器中处理。如果它是堆上对象的成员变量,那么它就在堆上,并通过偏移量引用它到对象中。如果它是全局/静态变量,则一旦程序完全加载到内存中,就会确定其地址。

C ++最终会编译成机器语言,并且通常在操作系统的上下文中运行,所以你可能想要了解一下Assembly基础知识,甚至是一些操作系统原理,以便更好地理解引擎盖下发生的事情。

答案 2 :(得分:1)

假设这是一个局部变量,则该变量在堆栈上分配 - 即在RAM中。编译器跟踪堆栈上的变量偏移量。在基本场景中,如果随后使用变量执行任何计算,则将其移动到处理器的一个寄存器中并且CPU执行计算。然后将结果返回到RAM。现代处理器将整个堆栈帧保留在寄存器中并具有多级寄存器,因此它可能变得非常复杂。

请注意二进制文件中不再提及“c”名称(除非您有调试符号)。二进制文件仅适用于内存位置。例如。它看起来像这样(简单的加法):

a = b + c

take value of memory offset 1 and put it in the register 1
take value of memory offset 2 and put in in the register 2
sum registers 1 and 2 and store the result in register 3
copy the register 3 to memory location 3

二进制文件不知道“a”,“b”或“c”。编译器只是说“a在内存1中,b在内存2中,c在内存3中”。 CPU只是盲目地执行编译器生成的命令。

答案 3 :(得分:0)

假设我们的程序以堆栈地址4000000

开头

当你调用一个函数时,根据你使用的堆栈数量,它会像这样“分配”

假设我们有2个整数(8字节)

int function()
{
    int a = 0;
    int b = 0;
}

然后会在集会中发生什么

MOV EBP,ESP //这里我们将堆栈地址的原始值(4000000)存储在EBP中,并在函数末尾将其恢复为4000000

SUB ESP, 8 //这里我们在堆栈中“分配”8个字节,这基本上只是将ESP addr减少了8个

所以我们的ESP地址已经改变了 4000000 至 3999992

程序知道第一个int的堆栈地址是“3999992”,第二个int是3999996到4000000

即使这几乎与编译器无关,知道这一点非常重要,因为当你知道如何“分配”堆栈时,你会意识到执行这样的事情是多么便宜

char my_array [20000]; 因为它所做的只是做sub esp,20000这是一个单独的汇编指令

但是如果你真的使用像memset(my_array,20000)那样的所有字节,那就是不同的历史。

答案 4 :(得分:0)

  

C ++如何在内存中访问此变量?

它没有!

您的计算机执行此操作,并通过将内存中变量的位置加载到寄存器中来指示如何执行此操作。这全部由汇编语言处理。我不会在这里详细介绍这些语言是如何工作的(你可以查阅它!)但这更像是C ++编译器的目的:将一组抽象的,高级的“指令”转换为计算机可以理解和执行的实际技术说明。您可以说汇编程序包含很多指针,但大多数都是文字而不是“变量”。