我们在C语言中有一个结构
struct info{
int no;
char first_name[20];
char last_name[20];
char status;
}
在运行时,当我们尝试按名称访问这些成员时,请说info_var.no
或info_var.first_name
,或者我们使用指向结构的指针info_ptr->no
或info_ptr->first_name
,如何访问这些个人成员?
我的意思是,结构将按成员存储为一些必要的填充,但运行时或编译器如何在编译时进行替换,如何通过名称访问这些个别成员?
我知道很多都是依赖于实现的,但是如果有人可以对任何实现有所了解,或者只是给出一个概述,那将非常好。
答案 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个字节。这是因为填充。
答案 2 :(得分:2)
直接访问结构和通过指针之间存在很大差异。
如果直接访问它,代码将使用虚构架构的简化汇编语法直接访问内存地址。以下示例访问成员status
,该成员存储在结构中的偏移44处:
MOVB varno+44, reg2
另一方面,如果您通过本地指针访问它,指针通常会存储在寄存器中。因此代码看起来像:
MOVB 44[reg1], reg2
最糟糕的情况是如果指针本身是全局指针,那么代码必须首先读取指针的值:
MOVL info_ptr, reg1
MOVB 44[reg1], reg2
在某些情况下,编译器可以在执行多次访问时缓存指针。但是,如果访问是写入(指针或字符),则编译器必须假定指针本身可能已被更改,因此从内存中重新读取它。
如果您的应用程序只包含一个全局结构,我强烈建议使用一个全局结构。
答案 3 :(得分:0)
每个字段都具有距struct
开头的预定偏移量。偏移量在编译时确定。机器代码只是将字段的偏移量添加到struct
的地址到字段的地址。
当您说"在运行时,当我们尝试按名称"访问这些成员时,请务必注意与该名称有关的所有工作在编译时完成。