结构体的实现机制

C语言中用结构体定义数据的顺序和它在内存中的数据布局是一致的。

#include <stdio.h> int main() { int i; struct information { int cpu_num; char cpu_name[50]; unsigned long cpu_speed; int cpu_price; }Info[3]={ {1,"AMD 1.2G 1987",1200,120}, {2,"INTEL 2.5G 1998",2500,220}, {3,"AMD 2.2G 2008",3000,420} }; for (i=0;i<3;i++) printf("%d %s %d %d/n/n",Info[i].cpu_num,Info[i].cpu_name,Info[i].cpu_speed,Info[i].cpu_price); return 0; }

反汇编代码如下所示:

int main() { 013213A0 push ebp 013213A1 mov ebp,esp 013213A3 sub esp,198h 013213A9 push ebx 013213AA push esi 013213AB push edi 013213AC lea edi,[ebp-198h] 013213B2 mov ecx,66h 013213B7 mov eax,0CCCCCCCCh 013213BC rep stos dword ptr es:[edi] ;以上是初始化工作 013213BE mov eax,dword ptr [___security_cookie (1327000h)] ;这是干嘛的呢 013213C3 xor eax,ebp 013213C5 mov dword ptr [ebp-4],eax int i; struct information { int cpu_num; char cpu_name[50]; unsigned long cpu_speed; int cpu_price; }Info[3]={ {1,"AMD 1.2G 1987",1200,120}, 013213C8 mov dword ptr [ebp-0D4h],1 ;设局部变量[ebp-0D4h]=1 013213D2 mov eax,dword ptr [string "AMD 1.2G 1987" (1325770h)] ;将全局变量指针1325770所指的4字节数据放到eax中 013213D7 mov dword ptr [ebp-0D0h],eax ;[ebp-0D0h]=[1325770h] 013213DD mov ecx,dword ptr ds:[1325774h] ;将全局变量指针1325774所指的4字节数据放到ecx中 013213E3 mov dword ptr [ebp-0CCh],ecx ;[ebp-0CCh]=[1325774] 013213E9 mov edx,dword ptr ds:[1325778h] ;将全局变量指针1325778所指的4字节数据放到edx中 013213EF mov dword ptr [ebp-0C8h],edx ;[ebp-0C8h]=[1325778] 013213F5 mov ax,word ptr ds:[0132577Ch] ;将全局变量指针132577c所指的2字节数据放到ax中 013213FB mov word ptr [ebp-0C4h],ax ;设局部变量[ebp-0C4h]=[132577c],占两个字节 01321402 xor eax,eax ;清空eax 01321404 mov dword ptr [ebp-0C2h],eax ;剩余的用00000000h填充,补充满50字节,x+4-(ebp-0D0h)=50,得x=ebp-A2,所以直到mov dword ptr [ebp-0A2h],eax 0132140A mov dword ptr [ebp-0BEh],eax 01321410 mov dword ptr [ebp-0BAh],eax 01321416 mov dword ptr [ebp-0B6h],eax 0132141C mov dword ptr [ebp-0B2h],eax 01321422 mov dword ptr [ebp-0AEh],eax 01321428 mov dword ptr [ebp-0AAh],eax 0132142E mov dword ptr [ebp-0A6h],eax 01321434 mov dword ptr [ebp-0A2h],eax 0132143A mov dword ptr [ebp-9Ch],4B0h ;设局部变量[ebp-9Ch]=4B0h=1200,此处为什么与上面相隔6个字节? 01321444 mov dword ptr [ebp-98h],78h ;设局部变量[ebp-98h]=78h=120 {2,"INTEL 2.5G 1998",2500,220}, 0132144E mov dword ptr [ebp-94h],2 ;过程与上面差不都,但是复制第二个变量时上面第四次是word为什么?为什么在结构体第二个成员变量与第三个成员变量之间隔两个字节,字符”/0”表示字符串结尾?那为什么不写入00h而是保留cch cch呢 01321458 mov eax,dword ptr [string "INTEL 2.5G 1998" (132575Ch)] 0132145D mov dword ptr [ebp-90h],eax 01321463 mov ecx,dword ptr ds:[1325760h] 01321469 mov dword ptr [ebp-8Ch],ecx 0132146F mov edx,dword ptr ds:[1325764h] 01321475 mov dword ptr [ebp-88h],edx 0132147B mov eax,dword ptr ds:[01325768h] 01321480 mov dword ptr [ebp-84h],eax 01321486 xor eax,eax 01321488 mov dword ptr [ebp-80h],eax 0132148B mov dword ptr [ebp-7Ch],eax 0132148E mov dword ptr [ebp-78h],eax 01321491 mov dword ptr [ebp-74h],eax 01321494 mov dword ptr [ebp-70h],eax 01321497 mov dword ptr [ebp-6Ch],eax 0132149A mov dword ptr [ebp-68h],eax 0132149D mov dword ptr [ebp-64h],eax 013214A0 mov word ptr [ebp-60h],ax 013214A4 mov dword ptr [ebp-5Ch],9C4h 013214AB mov dword ptr [ebp-58h],0DCh {3,"AMD 2.2G 2008",3000,420} 013214B2 mov dword ptr [ebp-54h],3 013214B9 mov eax,dword ptr [string "AMD 2.2G 2008" (132574Ch)] 013214BE mov dword ptr [ebp-50h],eax 013214C1 mov ecx,dword ptr ds:[1325750h] 013214C7 mov dword ptr [ebp-4Ch],ecx 013214CA mov edx,dword ptr ds:[1325754h] 013214D0 mov dword ptr [ebp-48h],edx 013214D3 mov ax,word ptr ds:[01325758h] 013214D9 mov word ptr [ebp-44h],ax 013214DD xor eax,eax 013214DF mov dword ptr [ebp-42h],eax 013214E2 mov dword ptr [ebp-3Eh],eax 013214E5 mov dword ptr [ebp-3Ah],eax 013214E8 mov dword ptr [ebp-36h],eax 013214EB mov dword ptr [ebp-32h],eax 013214EE mov dword ptr [ebp-2Eh],eax 013214F1 mov dword ptr [ebp-2Ah],eax 013214F4 mov dword ptr [ebp-26h],eax 013214F7 mov dword ptr [ebp-22h],eax 013214FA mov dword ptr [ebp-1Ch],0BB8h 01321501 mov dword ptr [ebp-18h],1A4h }; for (i=0;i<3;i++) 01321508 mov dword ptr [ebp-0Ch],0 ;局部变量[ebp-0Ch]=i=0 0132150F jmp main+17Ah (132151Ah) ;典型的FOR循环结构无条件跳转到 01321511 mov eax,dword ptr [ebp-0Ch] ;eax=i 01321514 add eax,1 ; 01321517 mov dword ptr [ebp-0Ch],eax ;使i加1 0132151A cmp dword ptr [ebp-0Ch],3 ;i<3? 0132151E jge main+1D1h (1321571h) ;如果i>=3则跳转到 printf("%d %s %d %d/n/n",Info[i].cpu_num,Info[i].cpu_name,Info[i].cpu_speed,Info[i].cpu_price); 01321520 mov eax,dword ptr [ebp-0Ch] ;eax=i 01321523 shl eax,6 ;i=i*2^6=i*64,得到结构体大小 01321526 mov esi,esp ;esi指向当前堆栈指针 01321528 mov ecx,dword ptr [ebp+eax-98h] ;ecx=局部变量[ebp+eax-98h],典型的数组或结构体寻址结构 0132152F push ecx ;参数入栈 01321530 mov edx,dword ptr [ebp-0Ch] ;edx=i 01321533 shl edx,6 ;i=i*64 01321536 mov eax,dword ptr [ebp+edx-9Ch] ;eax=局部变量[ebp+edx-9Ch] 0132153D push eax ;参数入栈 0132153E mov ecx,dword ptr [ebp-0Ch] 01321541 shl ecx,6 01321544 lea edx,[ebp+ecx-0D0h] ;edx指向字符串起始位置 0132154B push edx ;参数入栈 0132154C mov eax,dword ptr [ebp-0Ch] 0132154F shl eax,6 01321552 mov ecx,dword ptr [ebp+eax-0D4h] ;ecx=局部变量[ebp+eax-0D4h] 01321559 push ecx ;参数入栈 0132155A push offset string "%d %s %d %d/n/n" (132573Ch) ;字符串地址入栈 0132155F call dword ptr [__imp__printf (13282BCh)] ;调用printf函数 01321565 add esp,14h ;从堆栈中弹出14h字节,14h/4=5个参数 01321568 cmp esi,esp ;C_CheckEsp 0132156A call @ILT+310(__RTC_CheckEsp) (132113Bh) 0132156F jmp main+171h (1321511h) ;无条件跳转到 return 0; 01321571 xor eax,eax ;清空eax } 01321573 push edx 01321574 mov ecx,ebp 01321576 push eax 01321577 lea edx,[ (13215A4h)] 0132157D call @ILT+130(@_RTC_CheckStackVars@8) (1321087h) 01321582 pop eax 01321583 pop edx 01321584 pop edi 01321585 pop esi 01321586 pop ebx 01321587 mov ecx,dword ptr [ebp-4] 0132158A xor ecx,ebp 0132158C call @ILT+25(@__security_check_cookie@4) (132101Eh) 01321591 add esp,198h ;从堆栈中弹出198h字节 01321597 cmp ebp,esp 01321599 call @ILT+310(__RTC_CheckEsp) (132113Bh) 0132159E mov esp,ebp 013215A0 pop ebp 013215A1 ret

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C 语言中没有内置的反射机制,但是你可以使用一些预处理器指令来实现类似的功能。 例如,你可以使用 `#define` 来定义一个类似于反射的宏,然后在结构中使用该宏来生成代码。 例如: ``` #define REFLECT(x) int x##_offset = offsetof(struct_name, x) struct struct_name { int a; REFLECT(a); char b; REFLECT(b); }; ``` 在这个例子中,`REFLECT(a)` 宏会生成一个 `a_offset` 变量,并将其赋值为 `a` 字段在结构中的偏移量。你可以使用该变量来获取结构中的字段,就像使用反射一样。 当然,这只是一种简单的实现方式,你也可以使用其他的技术来实现更复杂的反射功能。 ### 回答2: 在C语言中,没有直接支持结构的反射。反射是指在程序运行时获取对象的信息和操作对象的能力。C语言是一种静态类型语言,因此在编译时需要明确知道对象的类型和属性,无法在运行时动态获取。 但是,我们可以通过一些技巧来模拟结构的反射。一个常见的方法是使用宏定义来定义结构及其属性,然后使用预处理指令来生成所需的代码。 以一个简单的例子来说明,假设有一个名为Person的结构,包含name和age两个属性。我们可以定义一个宏来生成访问这两个属性的函数: ```c #include <stdio.h> #define DEFINE_PERSON_STRUCT \ typedef struct { \ char* name; \ int age; \ } Person; \ #define GET_NAME(person) (person.name) #define GET_AGE(person) (person.age) int main() { Person person; person.name = "Alice"; person.age = 25; printf("Name: %s\n", GET_NAME(person)); printf("Age: %d\n", GET_AGE(person)); return 0; } ``` 在上述代码中,我们使用宏定义了Person结构及其属性,然后定义了两个宏来获取name和age属性的值。在main函数中,我们创建了一个Person结构对象person,并为其属性赋值,然后使用宏来获取属性值并进行打印。 通过这种方法,我们可以在C语言中模拟结构的反射。但需要注意的是,这种方法需要提前定义好所有可能的结构及其属性,并使用预处理指令来生成代码,不具有动态性。 ### 回答3: C语言本身并没有提供结构的反射机制,但可以通过一些技巧来实现结构的反射。 一种实现方式是使用宏定义来模拟反射。首先,我们可以定义一个宏来定义结构,该宏可以在结构中添加一个成员变量用于表示结构的类型。例如: ```c #define REFLECT_STRUCT(type) \ typedef struct type##_struct { \ int type; \ /* other members... */ \ } REFLECT_STRUCT(Person); ``` 然后,我们可以使用另一个宏来为结构增加一个getter函数,通过该函数可以获取结构的类型。例如: ```c #define GET_STRUCT_TYPE(ptr) (ptr->type) int getPersonType(Person* person) { return GET_STRUCT_TYPE(person); } ``` 这样,我们就可以通过调用`getPersonType`函数来获取`Person`结构的类型。 另一种实现方式是使用代码生成工具,例如使用脚本语言编写一个根据结构定义生成反射代码的工具。该工具可以读取结构定义的源文件,然后根据结构的成员生成对应的getter函数和类型信息。生成的代码可以包含一个`getStructType`函数来获取结构的类型。 这样,我们在使用结构时就可以通过调用`getStructType`函数来获取结构的类型。 总结来说,C语言本身并没有提供直接的结构反射机制,但我们可以使用宏定义或代码生成工具来模拟实现反射。这些方法可以通过一些技巧来获取结构的类型信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值