我对此很新,所以如果问题没有意义,我会提前道歉。
如果我是正确的,c#中的int是4个字节。如果我有声明:
int x;
我认为这占用了4个字节的内存。如果每个存储器地址空间是1个字节,那么这将占用四个地址槽?如果是这样,x如何映射到四个地址位置?
答案 0 :(得分:11)
如果我有语句
int x;
,我会认为这占用了4个字节的内存。 x如何映射到四个字节的地址?
首先,迈克是正确的。 C#专门设计,因此您无需担心这些问题。让内存管理员为您处理;它做得很好。
假设您确实希望看到香肠是如何制作的,那么您的假设是不合理的。此声明不 导致任何要消耗的内存。如果它确实导致内存被消耗,则int消耗四个字节的内存。
局部变量(*)有两种方式可以不占用内存。首先是它从未使用过:
void M()
{
int x;
}
编译器可以足够聪明地知道x永远不会被写入或读取,并且可以在法律上完全省略。显然,它不会占用任何记忆。
第二种不占用内存的方法是抖动选择注册本地。它可以专门为该局部变量分配一个机器寄存器。然后该变量没有与之关联的地址,因为显然寄存器没有地址。(**)
假设本地占用内存,抖动负责跟踪内存的位置。
如果本地是一个完全正常的局部,那么抖动会使堆栈指针碰到四个字节,从而在堆栈上保留四个字节。然后它将这四个字节与本地相关联。
如果本地是匿名函数的本地外部本地,迭代器块的本地或异步方法的本地,则C#编译器将生成本地作为类的字段;抖动要求垃圾收集器分配类实例,抖动将本地与垃圾收集器与该实例关联的内存缓冲区的开头的特定偏移量相关联。
所有这些都是实施细节,随时可能发生变化;不要依赖它。
(*)我们知道它是一个局部变量,因为你说它是一个语句。字段声明不是语句。
(**)如果不安全代码采用本地地址,显然无法注册。
答案 1 :(得分:5)
可以说有很多(我的意思是很多)。您遇到的各种主题包括stack,symbol table,memory management,memory hierarchy,......我可以继续使用。
但是,既然你是新人,我会尝试给出一个更简单的答案:
在程序(例如int)中创建变量时,您告诉编译器在内存中为该数据保留空间。 int是4个字节,因此保留4个连续字节。您所指的内存位置仅指向开头。后来知道长度是4个字节。
现在,内存位置(在您提供的情况下)实际上并没有以与变量相同的方式保存。每次有一个需要x
的命令时,该命令将替换为显式获取该内存位置的命令。换句话说,地址保存在程序的“代码”部分,而不是“数据”部分。
这只是真正的,真正高概述。希望它有所帮助。
答案 2 :(得分:2)
你真的不需要担心这些事情,因为在C#中你无法编写可以利用这些信息的代码。
但是如果你必须知道,当我们指示CPU访问x的内容时,在机器代码级别,它将使用这四个字节中第一个的地址来引用。执行此操作的机器指令还将包含有关要访问的字节数的信息,在本例中为四个。
答案 3 :(得分:1)
如果是int x;在函数内声明,然后变量将在堆栈上分配,而不是堆或全局内存。编译器符号表中的x地址将引用四字节整数的第一个字节。但是,由于它位于堆栈中,因此记住的地址将是堆栈上的偏移量,而不是物理地址。然后,将使用来自当前堆栈指针的偏移量通过指令引用该变量。
假设32位运行时,堆栈上的偏移量将对齐,因此地址是4个字节的倍数,即偏移量将以0,4,8或0x0c结束。
此外,因为80x86系列是little-endian,所以整数的第一个字节将是最不重要的,第四个字节将是最重要的,例如十进制值1,000,000将存储为四个字节0x40 0x42 0x0f 0x00。