57-函数结构转换

原创 2016年04月26日 12:32:17

57-函数结构转换

在函数调用的执行代码中我们会看到这样一些强制转换:

EX(function_state).function = (zend_function *) op_array;

或者:

EG(active_op_array) = (zend_op_array *) EX(function_state).function;

这些不同结构间的强制转换是如何进行的呢?

首先我们来看zend_function的结构,在Zend/zend_compile.h文件中,其定义如下:

typedef union _zend_function {
    zend_uchar type;    /* MUST be the first element of this struct! */

    struct {
        zend_uchar type;  /* never used */
        char *function_name;
        zend_class_entry *scope;
        zend_uint fn_flags;
        union _zend_function *prototype;
        zend_uint num_args;
        zend_uint required_num_args;
        zend_arg_info *arg_info;
        zend_bool pass_rest_by_reference;
        unsigned char return_reference;
    } common;

    zend_op_array op_array;
    zend_internal_function internal_function;
} zend_function;

这是一个联合体,我们来温习一下联合体的一些特性。 联合体的所有成员变量共享内存中的一块内存,在某个时刻只能有一个成员使用这块内存, 并且当使用某一个成员时,其仅能按照它的类型和内存大小修改对应的内存空间。 我们来看看一个例子:

#include <stdio.h>
#include <stdlib.h>

int main() {
    typedef  union _utype 
    { 
        int i; 
        char ch[2]; 
    } utype; 

    utype a;

    a.i = 10;
    a.ch[0] = '1'; 
    a.ch[1] = '1';

    printf("a.i= %d a.ch=%s",a.i, a.ch); 
    getchar();

    return (EXIT_SUCCESS);
}

程序输出:a.i= 12593 a.ch=11 当修改ch的值时,它会依据自己的规则覆盖i字段对应的内存空间。 ‘1’对应的ASCII码值是49,二进制为00110001,当ch字段的两个元素都为’1’时,此时内存中存储的二进制为 00110001 00110001 转成十进制,其值为12593。

回过头来看zend_function的结构,它也是一个联合体,第一个字段为type, 在common中第一个字段也为type,并且其后面注释为/* Never used*/,此处的type字段的作用就是为第一个字段的type留下内存空间。并且不让其它字段干扰了第一个字段。 我们再看zend_op_array的结构:

struct _zend_op_array {
    /* Common elements */
    zend_uchar type;
    char *function_name;        
    zend_class_entry *scope;
    zend_uint fn_flags;
    union _zend_function *prototype;
    zend_uint num_args;
    zend_uint required_num_args;
    zend_arg_info *arg_info;
    zend_bool pass_rest_by_reference;
    unsigned char return_reference;
    /* END of common elements */

    zend_bool done_pass_two;
    ....//  其它字段
}

这里的字段集和common的一样,于是在将zend_function转化成zend_op_array时并不会产生影响,这种转变是双向的。

再看zend_internal_function的结构:

typedef struct _zend_internal_function {
    /* Common elements */
    zend_uchar type;
    char * function_name;
    zend_class_entry *scope;
    zend_uint fn_flags;
    union _zend_function *prototype;
    zend_uint num_args;
    zend_uint required_num_args;
    zend_arg_info *arg_info;
    zend_bool pass_rest_by_reference;
    unsigned char return_reference;
    /* END of common elements */

    void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
    struct _zend_module_entry *module;
} zend_internal_function;

同样存在公共元素,和common结构体一样,我们可以将zend_function结构强制转化成zend_internal_function结构,并且这种转变是双向的。

总的来说zend_internal_function,zend_function,zend_op_array这三种结构在一定程序上存在公共的元素, 于是这些元素以联合体的形式共享内存,并且在执行过程中对于一个函数,这三种结构对应的字段在值上都是一样的, 于是可以在一些结构间发生完美的强制类型转换。 可以转换的列表如下:

  • zend_function可以与zend_op_array互换
  • zend_function可以与zend_internal_function互换

但是一个zend_op_array结构转换成zend_function是不能再次转变成zend_internal_function结构的,反之亦然。

其实zend_function就是一个混合的数据结构,这种结构在一定程序上节省了内存空间。

结构类型、结构函数和构造函数

在初学C#的时候,有三个概念可能会容易搞混——结构类型、结构函数、构造函数。          结构类型是由几个数据组成的数据结构,这些数据可能有不同的的类型。结构就是把这些不同类型的数据组合在一起,...
  • u011416044
  • u011416044
  • 2013年08月26日 20:00
  • 1704

57-其它套接字选项

还有很多套接字选项,比如 SO_KEEPALIVE,SO_RCVBUF, SO_SNDBUF 等,这些就不打算在博客里详细去实验,大家可以自己使用 opt 程序进行实验。以后如果我们遇到了非得用它的时...
  • q1007729991
  • q1007729991
  • 2017年04月26日 14:22
  • 315

Python语法 之 结构与函数

综述:计算机的流程控制主要通过三种结构来控制的:顺序结构,选择结构,循环结构。下面讲述下python语言的这三种结构的语法模式。选择结构并列if语句所谓选择结构就是一个或多个条件判断,及其执行语句组成...
  • lanxueCC
  • lanxueCC
  • 2016年12月23日 17:24
  • 716

9.IDA-重新设置函数类型、创建数组结构

重新设置函数类型 写一个简单的代码做测试: int fun(int a, double b) { return 0; } int _tmain(int argc, _TCHAR* argv[]) ...
  • hgy413
  • hgy413
  • 2012年06月16日 21:25
  • 2482

与指向的类型无关;转换要求 reinterpret_cast、c 样式转换或函数样式转换

C++写的MFC(ANSI),之前好好地,后来再打开出现这个问题,很明显就是配置问题。 问题如下: ------ 已启动生成: 项目: winsocket, 配置: Debug Win32 ---...
  • chglory
  • chglory
  • 2016年10月21日 09:39
  • 875

函数栈帧图解

我们知道内存空间大致可以用下图表示: 而函数在调用的时候都是在栈空间上开辟一段空间以供函数使用,所以下面来详细谈一谈函数的栈帧结构。 如...
  • stay_the_course
  • stay_the_course
  • 2016年11月05日 11:55
  • 2096

LintCode 57-三数之和

本人电子系,只是一学生。心喜计算机,小编以怡情。public ArrayList threeSum(int[] numbers) { // write your code here ...
  • Jason__Liang
  • Jason__Liang
  • 2016年12月23日 22:11
  • 127

57- 打印钻石图形

题目描述 给定一个正奇数n,请你打印一个n*n规模的钻石图形。钻石部分用'D'表示,其余部分用'*'表示。详见样例。 输入 一个正奇数n(3≤n≤30) 输出 一个钻石图形。 样例输...
  • foreverlove111
  • foreverlove111
  • 2017年06月04日 21:19
  • 261

57-控制器的生命周期

控制器的生命周期 1.通过控制器的生命周期可以了解到: 1>控制器的View什么时候创建,什么时候销毁。 2>控制器的view是懒加载的,例如导航控制器有2个子控制器,先会加载第一个子控制器的vie...
  • good_sister
  • good_sister
  • 2015年01月21日 12:25
  • 253

PHP的语言结构和函数的区别

php语言结构函数  相信大家经常看到对比一些PHP应用中,说用isset() 替换 strlen(),isset比strlen执行速度快等。 例子:         if ( iss...
  • amao1
  • amao1
  • 2015年10月20日 06:28
  • 914
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:57-函数结构转换
举报原因:
原因补充:

(最多只允许输入30个字)