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

时间:2012-01-09 10:22:03

标签: c struct

我们在C语言中有一个结构

struct info{
    int no;
    char first_name[20];
    char last_name[20];
    char status;
}

在运行时,当我们尝试按名称访问这些成员时,请说info_var.noinfo_var.first_name,或者我们使用指向结构的指针info_ptr->noinfo_ptr->first_name,如何访问这些个人成员?

我的意思是,结构将按成员存储为一些必要的填充,但运行时或编译器如何在编译时进行替换,如何通过名称访问这些个别成员?

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

4 个答案:

答案 0 :(得分:5)

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

没有动态查找变量名称,例如Python

答案 1 :(得分:2)

通过指针或对象进行访问没有任何区别,实际上info_ptr->no相当于(*info_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.无论如何,应该是相同的:)。

答案 2 :(得分:2)

直接访问结构和通过指针之间存在很大差异。

如果直接访问它,代码将使用虚构架构的简化汇编语法直接访问内存地址。以下示例访问成员status,该成员存储在结构中的偏移44处:

MOVB  varno+44, reg2

另一方面,如果您通过本地指针访问它,指针通常会存储在寄存器中。因此代码看起来像:

MOVB  44[reg1], reg2

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

MOVL  info_ptr, reg1
MOVB  44[reg1], reg2

在某些情况下,编译器可以在执行多次访问时缓存指针。但是,如果访问是写入(指针或字符),则编译器必须假定指针本身可能已被更改,因此从内存中重新读取它。

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

答案 3 :(得分:0)

每个字段都具有距struct开头的预定偏移量。偏移量在编译时确定。机器代码只是将字段的偏移量添加到struct的地址到字段的地址。

当您说"在运行时,当我们尝试按名称"访问这些成员时,请务必注意与该名称有关的所有工作在编译时完成。