首页 | 互联网 | IT动态 | IT培训 | Cisco | Windows | Linux | Java | .Net | Oracle | 软件测试 | C/C++ | 嵌入式开发 | 存储世界 | 服务器
网络设备 | IDC | 安全 | 求职招聘 | 数字网校 | 网页设计 | 平面设计 | 技术专题 | 电子书下载 | 教学视频 | 源码下载 | 搜索 | 博客 | 论坛
 您现在的位置: 中国IT实验室 >> 游戏开发 >> 游戏程序设计 >> 正文
Quake源碼的一個參數引用技巧
来源:天新网 作者:佚名 时间:2008-8-4

 曾經在Quake源碼里看到下面一段代碼: 
int VM_Call( vm_t *vm, int instruction, ... ) {
 va_list argptr;
 int  arg0;
 int  arg1;
 int  arg2;
 int  arg3;
 int  arg4;
 int  arg5;
 int  arg6;

 if( !vm ) {
  Com_Error( ERR_FATAL, "VM_Call with NULL vm" );
 }

 //Com_Printf( "VM_Call( %i )\n", instruction );

 va_start( argptr, instruction );
 arg0 = va_arg( argptr, int );
 arg1 = va_arg( argptr, int );
 arg2 = va_arg( argptr, int );
 arg3 = va_arg( argptr, int );
 arg4 = va_arg( argptr, int );
 arg5 = va_arg( argptr, int );
 arg6 = va_arg( argptr, int );
 va_end( argptr );

 return vm->vmMain( instruction, arg0, arg1, arg2, arg3, arg4, arg5, arg6 );
}
     引起我興趣的是VM_Call( vm_t *vm, int instruction, ... ) 中參數聲明的部分."..."這個關鍵字我是從來沒有看見過,覺得很是新奇.它的作用感覺是要騙過編譯器,使它不對vm_t *vm, int instruction以後所傳入的參數類型和個數進行檢查.換句話說就是不論函數調用者有多少參數,都可以一次性地壓入堆棧中.那麼函數本身如何去利用堆棧中的參數呢?我們還是先去看看下面系統定義的宏:
typedef char *  va_list;
#ifdef  _M_IX86


#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

#define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap)      ( ap = (va_list)0 )

#elif   defined(_M_MRX000)


/* Use these types and definitions if generating code for MIPS */

#define va_start(ap,v) ap  = (va_list)&v + sizeof(v)
#define va_end(list)
#define va_arg(list, mode) ((mode *)(list =\
 (char *) ((((int)list + (__builtin_alignof(mode)<=4?3:7)) &\
 (__builtin_alignof(mode)<=4?-4:-8))+sizeof(mode))))[-1]

/*  +++++++++++++++++++++++++++++++++++++++++++
    Because of parameter passing conventions in C:
    use mode=int for char, and short types
    use mode=double for float types
    use a pointer for array types
    +++++++++++++++++++++++++++++++++++++++++++ */


#elif   defined(_M_ALPHA)


        我們知道函數內部使用的變量都是在堆棧中開闢空間,而且堆棧的生長方向是從高地址向低地址生長.如果跳過函數定義的第一個變量,我們就來到了存放參數的棧頂,也就是#define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )
這個宏的涵義.#define va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )則是把參數逐個的從堆棧中取出,但並不是出棧,這裡要注意.
        可是為甚麼要採用這種看起來比較彆扭的方式來傳遞參數呢?主要原因是讓代碼能夠在多個編譯器上編譯,並且保證執行效果一樣.每種編譯器所定義的原始數據類型的字节長度也許是不同的.

【责编:snow】

中国IT教育热线咨询

相关文章
PS特效:腐蚀金属牌上的镂空字
推荐文章

 精彩友情推荐
·Asp源码 PHP源码
·CGI源码 JSP源码
·建站书籍教程
·服务器软件 .net源码
·建站工具软件
·IDC资讯大全
·机房品质万里行
·IDC托管必备知识
·全国IDC报价
·网站推广优化
 基础入门  开发文档
 最新推荐
  多数的Windows程序都需要Windows.h和Windowsx.h这两个头文件,要确保使用它们。当然,你还需要其它......
游戏引擎演化史
在Windows上安装OGRE的方法
关于滤镜遮罩概念,Sobel 遮罩
游戏开发新手入门之Windows编程
游戏开发新手入门之位图化图形
教你实现卡通渲染的另类勾边方法
游戏设计大师谈如何成为一名游戏设
Visual C#编写 3D游戏框架示例
真正的 Java 学习从入门到精通
游戏开发经验——游戏开发的基本常
  为什么要研究攻击行为在人类有记载的5600年的历史中,共计发生了14,400次战争;今天,平均一天要发生............
游戏开发中显示对话的特殊句法
游戏原型设计的介绍
网络游戏中的攻击行为
谈动作类游戏的必要条件
规则的多元分析模式
载入位图文件到DirectDraw
Archer Game Suite 是什么?
浅谈游戏企划-新手入门篇
暴雪称霸游戏业界的六大秘密绝招
骨骼动画及示例Skinned Mesh的解析
  培训中心