Rise的自留地

记录生活中的点滴,分享编程技术和游戏开发经验。

0%

作者:scottier   

剑道, 只是我从小到大从各种各样的媒体中得出的印象.   

因为喜欢剑术, 所以想做一个剑客. 在还没有做剑客时, 就想像自己有一把好剑, 威风凛凛地站在风中, 身边的树叶飘飘......, 一幅很酷的样子. 做了剑客后发现, 想找一把好剑不容易, 于是, 行侠江湖的几年中, 在找一把好剑.
  
终于过了几年, 有点胡子了, 有个和尚或老道看你有几分仁义的样子, 指了个好剑的方向. 结果, 你以前做梦都在想像的举剑一睹出现了, 当然, 是给自己看的, 注意, 要披一件大衣, 找个风口, 别忘了边上该有很多枯叶.POS摆完, 也该练点真功夫了, 要不真浪费了这么多年的追求, 又被别人数落个"金玉其表"的评价. 于是你练呀练呀, 总算有一天, 有一个你不认识的人叫了你一声"高手". 听第一遍时你还以为他在叫别人. 那天晚上你睡觉都在偷笑.   

然后, 你发现与人交手时, 的确顺手了很多. 每与一个曾经的对手交手后,你的信心都更增加一份. 你非常的爱护那把剑, 所以你常在无人的时候, 在林子里舞剑, 学习怎样提高你的剑气. 日子又过了很久, 你的剑气与日俱增,现在, 江湖中到处传颂你那"威风凛凛地站在风中, 身边的树叶飘飘......,一幅很酷的样子". 很多的小年青因为你, 也立誓想做一个剑客.   

终于有一天, 你发现自己很无聊. 在你眼中, 天下已没有什么高手了, 而自己的剑术好像也没有办法提高了. 你只是觉的闷, 奇怪天下居然还有你能做到头的事, 但是你隐约中又觉的自己还差一些. 你非常的爱护那把老剑, 你已能做到人剑一体了. 只有在一个人舞剑时, 你才能略感欣喜. 那种当初寻剑的回忆,那些练剑的回忆, 那些护剑的回忆, 在舞剑时, 一幕幕地划过脑海. 在别人看来, 你已是天下第一剑客了, 你的举手投足无不说明, 你是天下第一的. 直到有一天早上醒来, 你发现剑没了.这种事总是传的很快, 那些平日里惧怕你的对手, 又开始在江湖中兴风作浪起来了, 有几次你与他们偶遇上时, 几乎拼的要死, 才逃走. 失去了剑等于失去了你自己. 江湖上到处都在找那把你失去的剑. 又是一场无止境的血战. 你突然觉的非常的无趣, 原来练剑一辈子, 剑一丢, 等于前功尽弃. 你找个安静的山谷, 想修隐起来, 人生哪, 真是一个没有定数的人生哪. 你在那谷儿中看鱼虫跃, 鸟儿飞, 一直想找到自己失剑后会退步的这么惨的原因.   

有一天, 你像往常一样出游, 在谷中闲逛, 有一只蛇从后面飞速地刺向你, 你在惊觉中, 猛地转身, 用手一挥, 眼前出现的是, 蛇被劈成了两截. 你顿悟,剑术中差的那一点正是"有剑似无剑, 无剑似有剑". 原来, 那把好老剑, 正是你在习剑中不可逾越的一个障碍. 你不禁感叹: 人生哪, 真是奇妙的人生哪.

你总算是悟到了剑道.

程序, 现在是我的职业, 一个差不多快被世间无数热爱或不热爱的人做烂的职业.   

因为喜欢程序, 所以想做一个程序员. 在还没有做程序员时, 就想像自己有一台好机子, 用着牛B的C/C++, 十指飞快地在键盘上移动, 最后一个大回车.....看到程序运行起来时, 很满足的样子. 做了程序后发现, 想有一台好机子, 想找一个好公司不容易, 刚习程序时, 编译环境最好是字符或图形化的, 在命令行上敲make, cc带一堆的参数, 真的很恐怖. 后来到了 WINDOWS下, 当然是VC,把工具栏上的按键设成自己有用的几个, 开个全屏模式, 最大化地利用屏幕,多爽. 可是机子是公共的, 有时候累了往边上一躺, 就听到同事蹑手蹑脚地在你的位置坐下, 按了几下MOUSE, 开始打FF8. 休息了一阵, 有了感觉, 想爬起来开工, 但一看到同事那幅沉醉的样子, 偶而还转过头来, 冲你一笑, 报歉地说这儿没有存盘点. 唉, 不容易, 谁叫他那台机子WINDOWS下只剩500MB的空间,而且只是6326的显卡呢. 又躺在了床上, 想着, 要是有一台机子多好, 没有一点空间是冗余的, 都只有我想要的东西装在硬盘里面, 什么时候有灵感, 什么时候就爬起来开工. 于是, 程序的几年中, 在找一台好机子.   
终于过了几年, 有了自己的笔记本, 真爽啊, 可以随便移动, 想在哪写就在哪写.装UNIX 装LINUX装WINDOWS装上C/C++, 笔记本摆在哪儿都不一样, 摆在破桌上,也让人想到一张美国西部"破桌, 笔记本, 通辑犯的海报, 手枪", 很浓的金黄色调的宣传画. 真酷. POS摆完, 也该练点真功夫了, 要不真浪费了这么多年的追求, 又被别人数落个"金玉其表"的评价. 于是你练呀练呀, 总算有一天, 有一个你不认识的人叫了你一声"高手". 听第一遍时你还以为他在叫别人. 那天晚上你睡觉都在偷笑.   

然后, 你有新任务时, 的确顺手了很多. 以前要用一天写的代码, 现在只要一个早晨了, 每完成一个完整的程序, 你都更增添了一份信心. 你不知疲倦地用C/C++写和各种各样的程序, 你坚信, 只有用C/C++的程序员才是真正的程序员. 你有点蔑视VB, DEPHI, 用它们写程序, 光是启动程序都让你觉的无法忍受, 更别提那些不简练的语法了. 用C/C++的水准越来越高, 你几乎可以用它来做任何事, 加上一点硬件, 你让你家的电饭堡每天6点开煮, 电视晚上7点开播, 还有指纹锁......有一天有一个你倾慕已久的水瓶座MM去你那儿玩, 被你家的半自动化所折服, 惊叹的爱上了你.   

终于有一天, 你发现自己很无聊. 在你眼中, 程序没有什么新意了, 无非就是空间与时间的平衡, 而自己的程序好像也没有办法提高了. 你只是觉的闷, 奇怪天下居然还有你能做到头的事, 但是你隐约中又觉的自己还差一些. 你非常的爱护那台赛扬老机, 你已能做到人机一体了. 只有在用它写自己想玩的游戏时, 你才能略感欣喜. 那种当初学C/C++的回忆, 那些攒机的回忆, 那些护机的回忆, 在键入{}时, 一幕幕地划过脑海. 在别人看来, 你已是天下第一程序员了,你的举手投足无不说明, 你是天下第一的. 直到有一次旅游回来, 你发现屋子被撬了,没有一样东西留下.这种事总是很影响你的程序思路的, 那些平日里出现的问题, 又开始在新的任务中使你痛苦万分了, 有几次你与它们偶遇上时, 几乎想的要死, 才想出来解决之道. 你常在用程序的过程中想用一个以前写的工具时, 却发现没有了, 要重头写过. 那种累的感觉一下子冲上心头, 但是你又不想用别人写的东西, 你根本不相信别人写的东西里面没有BUG. 你觉的非常的无趣, 原来程序一辈子, 机子一丢, 等于前功尽弃. 你辞了工作, 想休息一阵, 人生哪, 真是一个没有定数的人生哪. 你路过图书馆时, 看着那些年青的大学生直直地盯着屏幕,脸上 整一幅痴迷的表情, 脑中一直想找到自己失机后, 写程序变的举步为艰的原因.   

有一天, 你在大学中闲逛, 你走在两个看起来像是大二的男生后面, 他们中的一个听起来水平更高一些, 因为他可以自己用C写一个俄罗斯方块, 另一个说: 哇塞, 这么利害, C语言我一直觉的很难, 像那些指针什么......", 水平更高一些的说: 我觉的你才利害, 用QUICK BASIC 那么不方便的东西都可以写出俄罗斯方块......". 你顿悟, 是呀, 你一生追求只用C/C++, 是为了什么? 程序只是用来解决实际问题的. 你不必拘泥在一种语言中而看不起别的语言, 你不必拘泥在自己的程式中而不用别人的工具呀. 原来, 语言成了你最大的障碍, 你不禁感叹: 人生哪, 真是奇妙的人生哪.   

你又找了份工作, 我们后来看到, 你在任何一台电脑中, 任何一种环境下, 任何一种语言, 甚至有时不用编程, 都可以解决所面对的任何问题.

你总算是悟到了编程之道.

初用Ubuntu感觉还不错,但发现没有RMVB的播放软件,下载个安装不上。
后来才发现, 不是有效的可执行文件。
转换之:
chmod +x RealPlayer10GOLD.bin
之后一路回车就OK了。
./RealPlayer10GOLD.bin


装完毕,在“应用程序”菜单中的“影音”中就出现了RealPlayer的菜单,结果一点反应也没。
发现是与SCIM冲突了,解决办法是,打开Realplayer的启动文件,这是一个shell脚本(默认位置为*(安装路径)/RealPlayer/realplay),直接在以#!/bin/sh开头的第一行下面(也就是第二行)添加下面语句:
export GTK_IM_MODULE=xim

按住Alt,用小键盘输入3到4个数字,再放开Alt键。
Symbol
Numeric Code
Symbol
Numeric Code
0134
·
0183 (250)
0135
¹
0185 (251)
0137
¼
0188 (172)
0149 (248)
½
0189 (171)
0153
¾
0190 (243)
§
0167 (245)
×
0215 (158)
¨
0168 (249)
ß
0223 (225)
©
0169 (184)
÷
0247 (246)
®
0174 (169)
ƒ
(159)
°
0176 (248)
º
(167)
²
0178 (253)
¿
(168)
³
0179 (252)
¢
(189)
µ
0181 (230)
¤
(207)
0182 (244)
±
(241)
还有很多没全试。

汤以仁厚收揽人心,争取人民的支持,有一次,他外出游玩,看见一人在树上挂起一张网,然后喃喃自语说:“不论天上来的,还是地面来的,凡是从四面八方来的鸟,都飞进网里来。”汤对他说:“你太过分了吧,怎么可以这样网尽杀绝呢!你撤掉三面,留下一面的网就可以了。”农民依言照办。汤祝告道:“鸟儿啊,你们愿意往左的就往左,往右的就往右,只有不听我话的鸟儿,才飞进网里来。”汤网开三(应该是一面吧,估计原作者写错了)面,恩及禽兽的事传开后,人民都称赞他对待百姓宽厚仁慈,纷纷拥护,汤的势力进一步壮大。


汤:汤,姓子,原名履,又称武汤、成汤、商汤、天乙、天乙汤,甲骨卜辞中称作唐、成、大乙、天乙、金文和周原甲骨文中称作成唐。汤是契的十四代孙。生卒年不详,商部落首领,灭而建商。在位13年,病死。葬处据传有六处,说法最多的是在毫(今河南省-商丘县北面)。

点绛唇
                          寇平仲(寇准)
水陌轻寒,社公雨足东风慢。
定巢新燕。
湿雨穿花转。
象尺熏炉,拂晓停针线。
愁蛾浅。
飞红零乱。
侧卧珠帘卷。

——————————-
寇准–刚直足智 功高名重  2003-6-21 寇准(961—1023),北宋政治家。字平仲,华州下邦(今陕西渭南)人。太平兴国进士。淳化五年(994年)为参知政事。景德元年(1004年)拜相。辽兵进攻宋朝时,他力排众议,主张坚决抵抗,促使真宗亲往澶州(今河南濮阳)督战,与辽订立澶渊之盟。不久被王钦若排挤罢相,出任陕州知州。晚年又被起用,天禧四年(1020年)又遭丁谓陷害,后被贬至雷州(今广东海康),卒于贬所。


也许自己想做的就是这样的人,努力之。

被 传下来的词就这几首。

VMware虚拟磁盘管理工具是VMware Workstation软件包里的一个软件,它让你用命令行或通过脚本来创建管理修改虚拟磁盘文件。它的一个重要的特性是能够增大虚拟磁盘大小,使虚拟磁盘的最大尺寸比刚创建时(定义的)更大。它是这样一种方法,如果你需要更多的磁盘空间在已经定义的虚拟机中,而你又不想添加另外一块硬盘或者用Ghost软件来传递虚拟磁盘上的数据到另外一块更大的虚拟磁盘上去时,你可以用改变虚拟磁盘最大尺寸方法来做。不过你可不能用这种方法对你的物理硬盘实施。
    另外一个功能是让你能够改变虚拟磁盘的类型。当你创建虚拟机时,你定义了虚拟磁盘空间的分配方式。你可以在以下选择一种分配方式:
- 所有的虚拟磁盘空间预分配。它相当于虚拟磁盘管理工具所说的预分配磁盘类型。
- 虚拟磁盘在开始时最小随着数据的增加而变大。它相当于虚拟磁盘管理工具所说的可增长磁盘类型。
使用虚拟磁盘管理工具,你能够更改虚拟磁盘的类型为预分配或可增长的、单个文件储存或每个文件大小为2GB的多文件方式。举个例子,你可以分配所有的虚拟磁盘空间,然后发现你需要收回一些主机上的硬盘空间。你能转换预分配的虚拟磁盘为可增长的虚拟磁盘,然后删除原来的那个虚拟磁盘文件。(这样)虚拟磁盘的大小将随着你的数据的增长而增长。
这些功能和使用脚本自动管理虚拟磁盘方法在VMware Workstation5.0版本中提供。
  你能够用虚拟磁盘管理工具完成以下任务:
- 使用脚本自动管理虚拟磁盘。
- 创建虚拟磁盘而不和任何一个虚拟机关联,举个例子,创建它作为样板。
- 在预分配和可增长的虚拟磁盘类型间进行转换。当你更改为可增长的虚拟磁盘类型,你就能够收回一些磁盘空间。你也能通过收缩虚拟磁盘来收回更多的空间。
- 增大虚拟磁盘的尺寸,使它比你创建时定义的尺寸更大。
- 磁盘碎片整理虚拟磁盘。
- 准备和收缩虚拟磁盘而不需要开启虚拟机进行(仅适用于Windows宿主机)。
你可以用虚拟磁盘管理程序管理由VMware GSX Server, VMware Workstation and VMware VirtualCenter(由GSX Server提供被VirtualCenter管理的虚拟磁盘)创建的虚拟磁盘。
  注意:你不能用虚拟磁盘工具创建物理磁盘。物理磁盘不能被虚拟磁盘管理工具或Workstation软件收缩。
  更多关于使用虚拟磁盘工具的信息,请阅读以下章节:
- 使用虚拟磁盘管理软件
- 使用虚拟磁盘管理实例

使用虚拟磁盘管理软件
    打开宿主机中的命令行或终端(Linux中的命令行),以运行虚拟磁盘管理软件。在Windows宿主机中,更改目录为你安装Workstation软件所在的目录。默认的安装目录为C:\Program Files\VMware\VMware Workstation。

  命令语法:
    vmware-vdiskmanager [选项]
  这里的选项你必须包含以下的一些选择项或参数
  选项和参数
  描述
<diskname>
    虚拟磁盘文件的名字。虚拟磁盘文件必须是.vmdk为扩展名。你能够指定一个你想要储存的虚拟磁盘文件的路径。如果你在你的宿主机中映射了网络共享,你也可以提供确切的虚拟磁盘文件的路径信息来创建虚拟磁盘在这个网络共享中

-c
    创建虚拟磁盘。你必须用-a, -s 和 -t 并指定选项参数,然后你需要指定所要创建的虚拟磁盘文件的文件名。

-r <sourcediskname>
    转换已经指定类型的虚拟磁盘的类型,结果会输出创建一个新的虚拟磁盘。你必须用-t选项来指定你想要转换成的磁盘类型,并且指定目标虚拟磁盘的文件名。
    一旦转换完成,你可以先测试虚拟磁盘以确保它能够像你所希望的那样工作,然后再删除原来的那个虚拟磁盘文件。
    为了让虚拟机重新认识转换后的虚拟磁盘,你应该使用虚拟机设置编辑器先从虚拟机中移除先前存在的虚拟磁盘,然后添加转换好的虚拟磁盘给虚拟机。

-x <n>[GB|MB] <diskname>
    增大虚拟磁盘到指定的容量。你必须指定新的更大尺寸的虚拟磁盘用GB或MB单位标示。你不能改变物理磁盘的大小。(废话)
  注意:在你运行虚拟磁盘管理软件前,你应该先备份虚拟磁盘文件。(因为不会创建新的文件,所以备份以防增大磁盘操作失败)

-d <diskname>
    对指定的虚拟磁盘碎片整理。你只能磁盘碎片整理可增长的虚拟磁盘。你不能磁盘碎片整理预分配的虚拟磁盘。

-p <mountpoint>
    为收缩磁盘做准备处理。如果虚拟磁盘被分成多个分区,每个分区必须被单独准备。分区(比如C:或D:)必须用VMware DiskMount工具映射。更多的应用VMware DiskMount映射和解除虚拟磁盘的映射的内容,请看VMware DiskMount用户手册,可以在VMware站点中 http://www.vmware.com/pdf/VMwareDiskMount.pdf   下载到。VMware DiskMount免费软件也可以在 http://www.vmware.com/download/ws/   页面下载到。
    在你对分区准备处理后,解除对此分区的映射。继续映射虚拟磁盘的其他每个分区,为收缩磁盘作准备处理直到完成虚拟磁盘上的所有分区的准备工作。
    你在同一时刻只能用VMware DiskMount映射虚拟磁盘的一个分区。你仅仅能在Windows宿主机上进行虚拟磁盘的收缩分区准备工作。

-k <diskname>
    收缩指定的虚拟磁盘。你只能够收缩可增长磁盘。你只能在Windows宿主机中(用这种方法)收缩虚拟磁盘。
    你不能够收缩有虚拟机快照的虚拟磁盘。你可以保持现有虚拟磁盘的状态,而用快照管理器删除所有快照。你也可以放弃自快照以来对虚拟磁盘所做的更改,恢复到快照时状态。

-a [ ide | buslogic | lsilogic ]
    指定磁盘适配器的类型。你在创建新的虚拟磁盘时必须指定其类型。选择以下类型之一:
    ide —— IDE接口适配器
    buslogic —— BusLogic SCSI接口适配器
    lsilogic —— LSI Logic SCSI接口适配器

-s <n> [GB|MB]
    指定虚拟磁盘的大小。确定大小用GB或MB做单位。你必须在创建磁盘时指定其大小。
    尽管你必须指定虚拟磁盘的大小,但当你增长它的大小时,你不能用-s这个选项。
    可以指定的磁盘大小规定:IDE和SCSI适配器都为最小100MB,最大950GB。

-t [0|1|2|3]
    你在创建一个新的虚拟磁盘或者重新配置一个虚拟磁盘时必须指定虚拟磁盘的类型。指定以下类型之一:
    0 —— 创建一个包含在单一虚拟文件中的可增长虚拟磁盘
    1 —— 创建一个被分割为每个文件2GB大小的可增长虚拟磁盘
    2 —— 创建一个包含在单一虚拟文件中的预分配虚拟磁盘
    3 —— 创建一个被分割为每个文件2GB大小的预分配虚拟磁盘

-q
    禁止虚拟磁盘管理程序写日志
    如果你允许记录日志,日志将会被虚拟磁盘管理程序产生并储存。在虚拟磁盘管理程序运行后,日志的名字和存放位置将会出现在命令行或终端中。

-n <source-disk>
    重命名指定的虚拟磁盘。需要指定命名后的虚拟磁盘名字。

使用VMware虚拟磁盘管理工具实例
    以下例子描述怎样使用虚拟磁盘管理工具。你需要在命令行中运行虚拟磁盘管理工具。

创建虚拟磁盘
    命令:vmware-vdiskmanager -c -t 0 -s 40GB -a ide myDisk.vmdk
    这个命令将创建一个40GB大小IDE接口的名字为myDisk的虚拟硬盘。虚拟磁盘包含在一个单一文件中。这个虚拟磁盘没有被预分配磁盘空间。
  实际命令输入:
    D:\Big Program Files\VMware\VMware Workstation>vmware-vdiskmanager -c -s 40Gb –a  ide -t 0 E:\myDisk.vmdk
  执行结果显示:
    Using log file C:\DOCUME1\AnEgg\LOCALS1\Temp\vmware-AnEgg\vdiskmanager.log
    Creating a monolithic growable disk ‘E:\myDisk.vmdk’
    Virtual disk creation successful.

转换一个虚拟磁盘
    转换一个预分配虚拟磁盘为可增长虚拟磁盘,用以下这个命令:
      vmware-vdiskmanager -r sourceDisk.vmdk -t 0 targetDisk.vmdk
    这个命令将转换磁盘从它的原始的预分配模式转变为包含在单一文件中的可增长虚拟磁盘。这个虚拟磁盘空间将不会被预先分配,虚拟磁盘工具将收回虚拟磁盘中的一些磁盘空间,而仅仅让里面的数据占用虚拟磁盘空间。
  实际命令输入:
    D:\Big Program Files\VMware\VMware Workstation>vmware-vdiskmanager -r “D:\WinXP
    SP2 V2.5\Windows XP Professional.vmdk” -t 0 “L:\Windows XP Professional.vmdk”
  执行结果显示:
    Using log file C:\DOCUME1\AnEgg\LOCALS1\Temp\vmware-AnEgg\vdiskmanager.log
    Creating a monolithic growable disk ‘L:\Windows XP Professional.vmdk’
    Convert: 100% done.
    Virtual disk conversion successful.

增大存在的虚拟磁盘的大小
    命令:vmware-vdiskmanager -x 40GB myDisk.vmdk
    这条命令将把虚拟磁盘myDisk.vmdk大小增大到40GB
  实际命令输入:
    D:\Big Program Files\VMware\VMware Workstation>vmware-vdiskmanager -x 40GB “D:\WinXP SP2 V2.5\Windows XP Professional S.vmdk”
  执行结果显示:
    Using log file C:\DOCUME1\AnEgg\LOCALS1\Temp\vmware-AnEgg\vdiskmanager.log
    Grow: 100% done.
    The old geometry C/H/S of the disk is: 8322/16/63
    The new geometry C/H/S of the disk is: 16383/16/63
    Disk expansion completed successfully.
    WARNING: If the virtual disk is partitioned, you must use a third-party
            utility in the virtual machine to expand the size of the
            partitions. For more information, see:
            http://www.vmware.com/support/kb/enduser/std_adp.php?p_faqid=1647
    创建好后,可以在磁盘管理中,看到未指派的空间。如果你想扩大磁盘分区的大小,可以用其他第三方软件来做。


#include "stdafx.h"
#include 
<stdio.h>
#include 
<stdarg.h>

int mul(int num,int data1,)
{
    
int total = data1;
    
int arg,i;
    va_list ap;
    va_start(ap,data1);
    
for(i=1;i<num;i++)
    {
        arg 
= va_arg(ap,int);
        total
*=arg;
    }
    va_end(ap);
    
return total;
}

long mul2(int i,)
{
    
int *p,j;
    p 
= &i+1;//p指向参数列表下一个位置
    long s = *p;
    
for (j=1;j<i;j++)
        s 
*= p[j];
    
return s;
}

int main()
{
    printf(
"%d\n",mul(3,2,3,5));
    printf(
"%d\n",mul2(3,2,3,5));
    
return 0;
}



printf的设计
#include "stdio.h"
#include 
"stdlib.h"
#include 
<stdarg.h>

void myprintf(char* fmt, )        //一个简单的类似于printf的实现,//参数必须都是int 类型
{
    
//char* pArg=NULL;               //等价于原来的va_list
    va_list pArg;
    
char c;
   
   
// pArg = (char*) &fmt;          //注意不要写成p = fmt !!因为这里要对参数取址,而不是取值
  
// pArg += sizeof(fmt);         //等价于原来的va_start         
    va_start(pArg,fmt);

    
do
    {
        c 
=*fmt;
        
if (c != '%')
        {
            putchar(c);            
//照原样输出字符
        }
        
else
        {
//按格式字符输出数据
            switch(*++fmt)
            {
            
case 'd':
                printf(
"%d",*((int*)pArg));           
                
break;
            
case 'x':
                printf(
"%#x",*((int*)pArg));
                
break;
            
case 'f':
                printf(
"%f",*((float*)pArg));
            
default:
                
break;
            }
            
//pArg += sizeof(int);               //等价于原来的va_arg
            va_arg(pArg,int);
        }
        
++fmt;
    }
while (*fmt != '\0');
    
//pArg = NULL;                               //等价于va_end
    va_end(pArg);
    
return;
}
int main(int argc, char* argv[])
{
    
int i = 1234;
    
int j = 5678;
   
    myprintf(
"the first test:i=%d",i,j);
    myprintf(
"the secend test:i=%f; %x;j=%d;",i,0xabcd,j);
    system(
"pause");
    
return 0;
}


可变参数在编译器中的处理 

    我们知道va_start,va_arg,va_end是在stdarg.h中被定义成宏的, 由于1)硬件平台的不同 2)编译器的不同,所以定义的宏也有所不同,下面以VC++stdarg.hx86平台的宏定义摘录如下(’"’号表示折行):
typedef char * va_list; 
#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 ) 

    定义_INTSIZEOF(n)主要是为了某些需要内存的对齐的系统.C语言的函数是从右向左压入堆栈的,(1)是函数的参数在堆栈中的分布位置.我们看到va_list被定义成char*,有一些平台或操作系统定义为void*.再看va_start的定义,定义为&v+_INTSIZEOF(v),&v是固定参数在堆栈的地址,所以我们运行va_start(ap, v)以后,ap指向第一个可变参数在堆栈的地址,如图:

高地址|-----------------------------| 
|函数返回地址 | 
|-----------------------------| 
|| 
|-----------------------------| 
|第n个参数(第一个可变参数) | 
|-----------------------------|<--va_start后ap指向 
|第n-1个参数(最后一个固定参数)| 
低地址
|-----------------------------|<-- &
图( 
1 ) 

    然后,我们用va_arg()取得类型t的可变参数值,以上例为int型为例,我们看一下va_argint型的返回值: j= ( *(int*)((ap += _INTSIZEOF(int))-_INTSIZEOF(int)) );
首先ap+=sizeof(int),已经指向下一个参数的地址了.然后返回ap-sizeof(int)int*指针,这正是第一个可变参数在堆栈里的地址(2).然后用*取得这个地址的内容(参数值)赋给j.

高地址|-----------------------------| 
|函数返回地址 | 
|-----------------------------| 
|| 
|-----------------------------|<--va_arg后ap指向 
|第n个参数(第一个可变参数) | 
|-----------------------------|<--va_start后ap指向 
|第n-1个参数(最后一个固定参数)| 
低地址
|-----------------------------|<-- &
图( 
2 ) 

    最后要说的是va_end宏的意思,x86平台定义为ap=(char*)0;使ap不再指向堆栈,而是跟NULL一样.有些直接定义为((void*)0),这样编译器不会为va_end产生代码,例如gcclinuxx86平台就是这样定义的.在这里大家要注意一个问题:由于参数的地址用于va_start,所以参数不能声明为寄存器变量或作为函数或数组类型.关于va_start, va_arg, va_end的描述就是这些了,我们要注意的是不同的操作系统和硬件平台的定义有些不同,但原理却是相似的

引用

DirectX SDK 2006学习笔记1——框架

友情提醒:所谓的框架是指SDK目录下\Samples\C++\Common路径下的DXUT系列函数包装。学习框架的前提是必须有足够的Windows API,GUI编程经验,必须熟悉Windows的消息机制,回调机制,最好有万行左右的C/C++编程经验。MFC在这里没有任何用处。另外我觉得最好在看程序之前对于D3D的所有概念有点了解,什么是vertex,texture,matrix,lighting,mesh等等,以及相关的数学概念。这些都可以在网上找到中文翻译,帮助你快速入门。