运行时如何从内存访问C结构成员?

运行时如何从内存访问C结构成员?,c,struct,C,Struct,我们有一个C语言的结构 struct info{ int no; char first_name[20]; char last_name[20]; char status; } 在运行时,当我们试图通过名称访问这些成员时,比如说info\u var.no或info\u var.first\u name,或者使用指向结构的指针info\u ptr->no或info\u ptr->first\u name,这些单独的成员是如何访问的 我的意思是,结构将被存储为一个成

我们有一个C语言的结构

struct info{
    int no;
    char first_name[20];
    char last_name[20];
    char status;
}
在运行时,当我们试图通过名称访问这些成员时,比如说
info\u var.no
info\u var.first\u name
,或者使用指向结构的指针
info\u ptr->no
info\u ptr->first\u name
,这些单独的成员是如何访问的

我的意思是,结构将被存储为一个成员一个成员地存储,并带有一些必要的填充,但是如果在编译时发生替换,那么运行时或者编译器如何通过它们的名称访问这些单独的成员呢


我知道很多都是依赖于实现的,但是如果有人能对任何实现有所了解或只是给出一个概述,那就太好了。

通过指针或对象访问没有什么区别,实际上
info\u ptr->no
相当于
(*info\u ptr)。no

实际的成员访问是特定于编译器的

假设你有:

class A
{
public:
   char c;
   int x;
   A() {};
};
以下是访问代码:

   A a;
004113BE  lea         ecx,[a] 
004113C1  call        A::A (4110E1h) 
   int y = a.x;
004113C6  mov         eax,dword ptr [ebp-8] 
004113C9  mov         dword ptr [y],eax 
因此,在本例中,编译器生成二进制文件,知道
x
相对于
a
存储在内存中的位置,即
a
实例中的8个字节。这是因为填充


编辑:我刚刚看到问题是关于C的。无论如何,应该是相同的:)。

在C中,工作是由编译器完成的。它将结构的数据成员编译为内存偏移量,并将其应用于结构的基址


变量名没有动态查找,例如在Python中,每个字段都有一个从结构开始的预定义偏移量。偏移量在编译时确定。机器代码只是将字段的偏移量从
结构的地址添加到字段的地址


当您说“在运行时,当我们试图通过名称访问这些成员时”,需要注意的是,所有与名称相关的工作都是在编译时完成的。

直接访问结构和通过指针访问结构之间有很大的区别

如果您直接访问它,代码将使用虚拟体系结构的简化汇编程序语法直接访问内存地址。下面的示例访问存储在结构中偏移量44处的成员
状态

MOVB  varno+44, reg2
另一方面,如果通过本地指针访问它,指针通常会存储在寄存器中。所以代码看起来像:

MOVB  44[reg1], reg2
最糟糕的情况是,如果指针本身是全局指针,那么代码必须首先读取指针的值:

MOVL  info_ptr, reg1
MOVB  44[reg1], reg2
在某些情况下,编译器可以在执行多次访问时缓存指针。但是,如果访问是写操作(指向指针或字符),那么编译器必须假设指针本身可能已更改,从而从内存中重新读取它


如果您的应用程序只包含一个全局结构,我强烈建议您使用一个全局结构。

您的代码假定对象是本地的,而在大多数情况下可能不是。因此,您的答案是错误的,特别是如果指针本身是一个全局变量。“看我的答案。”林德丹瑟我对此表示怀疑。你不能在标准没有明确规定的事情上说“这是错误的”。我可以编写自己的编译器,遵守标准,并以我在这里描述的方式访问内存。没有一条规则,我只是粘贴了一个可能性。这段代码是由MSVC2005在Win32平台下生成的,没有任何优化。我指定它高度依赖于此,这是错误的,因为您使用的一般语句是“通过指针或对象访问没有任何区别”。在这种特殊情况下,它不是,但在更常见的情况下,结构是一个全局变量,它肯定会产生影响。事实上,作为编译器开发人员,我会认为这是一个“经常被问到的问题”,我认为教人们通常与生成的代码有很大的区别是非常重要的。Lindydancer再次指出,生成的代码不是标准的一部分。code>p->f
被翻译成
(*p).f
是。这是真的,但这不是问题所在。仅仅因为您可以将
p->f'转换为
(*p).f
,这并不意味着像
s.f
这样的指针访问将生成与直接访问相同的代码。事实上,情况正好相反。Edit:补充说汇编程序语法是一个虚构的机器。