分享
 
 
 

使用 C 语言的“准元程序”设计

王朝c/c++·作者佚名  2006-02-01
窄屏简体版  字體: |||超大  

1. 将 C 语言的预编译语言看成是“元语言”,使用该元语言进行程序设计。

2. 但为什么叫“准元程序”,是因为 C 语言的预编译语言没有迭代结构,所以C 语言的元程序语言不是图灵完备的。

a) 举个简单的例子,我们无法用 C 语言的“元语言”写出一个计算 factorial(x)——x 的阶乘的程序;而用 C++的模板就可以(使用模板特化)。因为这需要语言的迭代结构。

b) C预编译语言没有迭代结构的原因是宏替换仅发生在源语言的宏调用中,预编译中的宏调用是不会发生替换的(除了条件编译中条件中对宏的调用)如:

#define macro1(x) (x)*(x)

#define macro2(x) macro1(x) // 这里不会发生宏替换

int y = macro2(100); // 宏替换仅发生在这里

但是,在条件编译中:

#if macro2(100) == 10000 // 这里会发生宏替换

….

#endif

因此,象这样的程序是错误的:

// fac.c, 计算 x 的阶乘

#if x <= 0

# define result 1

#else

# undef temp_x

# define temp_x (x - 1)

# undef x

# define x temp_x

# include "fac.c"

# undef temp_result

# define temp_result result * x

# undef result

# define result temp_result

#endif

3. 虽然如此,用 C 语言的预编译能力,在很多时候还是可以写出很好的程序,可以尽可能地减少代码冗余,增强程序性能。程序的可读性,也许增加了,也许减少了;但是在这个探索的过程中,很可能对问题的认识更深刻了,问题得到了更高程度的抽象。

4. 元程序使用的几个重要重要指令:

a) #define

用来定义“模板参数”

b) #undef

用来清除“模板参数”

c) #include

用来定义“模板体”

d) 符号展开连接:

i. #define CAT_TOKEN_1(t1, t2) t1##t2

ii. #define CAT_TOKEN(t1, t2) CAT_TOKEN_1(t1,t2)

CAT_TOKEN_1 直接将 t1和t2连接成 t1t2,而

CAT_TOKEN 将t1和t2展开后再连接,如:

#define t1 I_am_

#define t2 lei_peng

CAT_TOKEN_1(t1, t2) 的结果是 t1t2

CAT_TOKEN(t1, t2) 的结果是 I_am_leipeng

CAT_TOKEN 相当有用。

e) 总体上讲,C++的元程序设计是函数式语言(类似 lisp),而C语言的元程序设计有点类似汇编语言,试看:

// C 元程序代码

#define param1 …..

#define param2 …..

#define param3 …..

#include “template.c”

#undef param1 // 这些 #undef 也可以位于 “template.c”之内

#undef param2

#undef param3

// 汇编的函数调用代码

Push param1

Push param2

Push param3

Call function

Add esp, 3 * 4 // 恢复堆栈,堆栈也可以在 function 的返回语句恢复

5. 实例:int bitblt(GdiDevice* dst, const GdiDevice* src,

int dx, int dy, int cx, int cy, int sx, int sy, BinaryOpCode op);

的实现

a) 这是一个性能要求相当高基本图像位传送函数,同时又有许多种位操作:

i. not,and,or,xor,…完备的布尔代数,共16种布尔操作,去掉全真和全假,是14种操作

ii. 许多种象素位数(1,2,4,8,16,24,32),甚至更多。

iii. 这些情况组合起来,共有 686种(7×7×14)这显然是一个“过于完备”)的集合。

iv. 如果按普通的方式编码,要写 686多个不同的函数,或者 switch…case中686种不同的 case。而这些代码都是非常相似的,如果把相同部分提取出来,把不同部分使用“模板”替换掉…..

v. 详细内容见代码,代码是非常短的(同时还有另外一个函数mergeblt,原型与bitblt相同,其中仅实现了16,24,32位象素),这些代码如果使用预编译器输出处理结果,有 6000 多行!:

6. 附件中有源程序代码

// 模板体,bitblt_body.c

//////////////////////////////////////////////////////////////////////////

MCASE(dstBits, srcBits, bitOpCode)

{

callerVars()

int dstRowBytes = ROW_BYTES_2(dstBits, dst);

int srcRowBytes = ROW_BYTES_2(srcBits, src);

int i;

PBYTE dstRow = dst->data + dy * dstRowBytes + PIX_POS_2(dstBits, dx);

PBYTE srcRow = src->data + sy * srcRowBytes + PIX_POS_2(srcBits, sx);

for (i = cy; i; --i)

{

PBYTE dstCol = dstRow;

PBYTE srcCol = srcRow;

int j;

for (j = cx; j; --j)

{

condition(dstCol, srcCol)

callBitOp(dstCol, srcCol);

}

dstRow += dstRowBytes;

srcRow += srcRowBytes;

}

}

return 0;

#undef bitOpCode

#undef doBitOp

// 相同象素位的不同位操作(14种)

#define bitOpCode opCopy

#define doBitOp(d, s) d = s

#include "bitblt_body.c"

#define bitOpCode opAnd

#define doBitOp(d, s) d &= s

#include "bitblt_body.c"

#define bitOpCode opOr

#define doBitOp(d, s) d |= s

#include "bitblt_body.c"

#define bitOpCode opXor

#define doBitOp(d, s) d ^= s

#include "bitblt_body.c"

#define bitOpCode opNotSrc

#define doBitOp(d, s) d = ~s

#include "bitblt_body.c"

#define bitOpCode opNotAnd

#define doBitOp(d, s) d = ~(d & s)

#include "bitblt_body.c"

#define bitOpCode opNotOr

#define doBitOp(d, s) d = ~(d | s)

#include "bitblt_body.c"

#define bitOpCode opNotXor

#define doBitOp(d, s) d = ~(d ^ s)

#include "bitblt_body.c"

#define bitOpCode opNotDestAnd

#define doBitOp(d, s) d = ~d & s

#include "bitblt_body.c"

#define bitOpCode opNotDestOr

#define doBitOp(d, s) d = ~d | s

#include "bitblt_body.c"

#define bitOpCode opNotDestXor

#define doBitOp(d, s) d = ~d ^ s

#include "bitblt_body.c"

#define bitOpCode opNotSrcAnd

#define doBitOp(d, s) d &= ~s

#include "bitblt_body.c"

#define bitOpCode opNotSrcOr

#define doBitOp(d, s) d |= ~s

#include "bitblt_body.c"

#define bitOpCode opNotSrcXor

#define doBitOp(d, s) d ^= ~s

#include "bitblt_body.c"

#undef callBitOp

#undef dstBits

#undef srcBits

#undef pSrcToColor

// blt_body.c, 所有象素位数的模板,这里只定义了 16,24,32三种象素的相互操作

// dst --- 16

#define dstBits 16

#define srcBits 16

#define pSrcToColor PCOLOR16_TO_32

#define callBitOp(pd, ps) doBitOp(*(UINT16*)pd,*(UINT16*)ps), pd+=2,ps+=2

#include "bitblt_op.c"

#define dstBits 16

#define srcBits 24

#define pSrcToColor PCOLOR24_TO_32

#define callBitOp(pd, ps) doBitOp(*(UINT16*)pd, PCOLOR24_TO_16(ps)), pd +=2, ps += 3

#include "bitblt_op.c"

#define dstBits 16

#define srcBits 32

#define pSrcToColor(x) *(x)

#define callBitOp(pd, ps) doBitOp(*(UINT16*)pd, PCOLOR32_TO_16(ps)), pd +=2, ps += 4

#include "bitblt_op.c"

// dst --- 24

#define dstBits 24

#define srcBits 16

#define pSrcToColor PCOLOR16_TO_32

#define callBitOp(pd, ps) doBitOp(pd[0], C16_R(*(UINT16*)ps)), doBitOp(pd[1], C16_G(*(UINT16*)ps)), doBitOp(pd[2], C16_B(*(UINT16*)ps)), pd +=3, ps += 2

#include "bitblt_op.c"

#define dstBits 24

#define srcBits 24

#define pSrcToColor PCOLOR24_TO_32

#define callBitOp(pd, ps) doBitOp(pd[0], ps[0]), doBitOp(pd[1], ps[1]), doBitOp(pd[2], ps[2]), pd +=3, ps += 3

#include "bitblt_op.c"

#define dstBits 24

#define srcBits 32

#define pSrcToColor(x) *(x)

#define callBitOp(pd, ps) doBitOp(pd[0], C32_R(*ps)), doBitOp(pd[1], C32_G(*ps)), doBitOp(pd[2], C32_B(*ps)), pd +=3, ps += 4

#include "bitblt_op.c"

// dst --- 32

#define dstBits 32

#define srcBits 16

#define pSrcToColor PCOLOR16_TO_32

#define callBitOp(pd, ps) doBitOp(*(UINT32*)pd, PCOLOR16_TO_32(ps)), pd +=4, ps += 2

#include "bitblt_op.c"

#define dstBits 32

#define srcBits 24

#define pSrcToColor PCOLOR24_TO_32

#define callBitOp(pd, ps) doBitOp(*(UINT32*)pd, PCOLOR24_TO_32(ps)), pd +=4, ps += 3

#include "bitblt_op.c"

#define dstBits 32

#define srcBits 32

#define pSrcToColor(x) *(x)

#define callBitOp(pd, ps) doBitOp(*(UINT32*)pd,*(UINT32*)ps), pd+=4, ps+=4

#include "bitblt_op.c"

// 函数体,适用于 bitblt 和 mergeblt,模板参数为 condition

static const unsigned char jump_table[] = {

0, bit_1, bit_2, 0, bit_4 , 0, 0, 0,

bit_8 , 0, 0, 0, bit_12, 0, 0, 0,

bit_16, 0, 0, 0, 0, 0, 0, 0,

bit_24, 0, 0, 0, 0, 0, 0, 0,

bit_32

};

int jump_index;

if (dst->colorBits > 32) return -1;

if (src->colorBits > 32) return -2;

if ((unsigned int)op >= (unsigned int)BinaryOpCode_Radix)

return -4;

jump_index =

jump_table[dst->colorBits] +

jump_table[src->colorBits] * bitRadix + op * bitRadix*bitRadix;

switch (jump_index)

{

default:

if (0 == jump_table[dst->colorBits])

return -1; // dst->colorBits error

else if (0 == jump_table[src->colorBits])

return -2; // src->colorBits error

else

return -3; // not support

#include "blt_body.c"

}

return -5; // it will not goes here

#undef condition

// gdi.h 定义图像基本类型和常量,及 utilities

#ifndef __GDI_H__

#define __GDI_H__

typedef enum BinaryOpCode

{

opCopy, // dst = src

opXor, // dst = src ^ dst

opAnd, // dst = src & dst

opOr, // dst = src | dst

opNotSrc, // dst = ~src

opNotAnd, // dst = ~(src & dst)

opNotOr, // dst = ~(src | dst)

opNotXor, // dst = ~(src ^ dst)

opNotDestAnd, // dst = ~dst & src

opNotDestOr, // dst = ~dst | src

opNotDestXor, // dst = ~dst ^ src

opNotSrcAnd, // dst = dst & ~src

opNotSrcOr, // dst = dst | ~src

opNotSrcXor, // dst = dst ^ ~src

// opSet, // dst = 1

// opClear, // dst = 0

BinaryOpCode_Radix

} BinaryOpCode;

typedef unsigned char BYTE, *PBYTE;

typedef unsigned long COLOR;

typedef unsigned short UINT16;

typedef unsigned long UINT32;

typedef struct _GdiDevice

{

unsigned int colorBits;

int width;

int height;

COLOR transparentColor;

int transparentTolerance;

COLOR* pallete;

PBYTE data;

} GdiDevice;

#define ROW_BYTES_2(colorBits, gdi) ((7 + (gdi)->width * colorBits) >> 3)

#define PIX_POS_2(colorBits, x) ((x * colorBits) >> 3)

#define ROW_BYTES(gdi) ((7 + (gdi)->width * (gdi)->colorBits) >> 3)

#define PIX_POS(gdi, x) ((x * (gdi)->colorBits) >> 3)

#endif

// bitblt.c

// bitblt 函数和 mergeblt的函数体

#include "gdi.h"

enum ColorBitKind

{

bitError = 0,

bit_1 = 1,

bit_2 = 2,

bit_4,

bit_8,

bit_12,

bit_16,

bit_24,

bit_32,

bitRadix

};

#define CAT_TOKEN1(t1, t2) t1##t2

#define CAT_TOKEN(t1, t2) CAT_TOKEN1(t1, t2)

#define MCASE(dstBits, srcBits, bitOpCode) case CAT_TOKEN(bit_, dstBits) + CAT_TOKEN(bit_, srcBits)*bitRadix + bitOpCode*bitRadix*bitRadix:

// 00RR-RRRR-RRRR-GGGG-GGGG-GGBB-BBBB-BBBB

// 0x3FF00000 0x000FFC00 0x000003FF

#define C32_R(c) (c >> 20 & 0x3FF)

#define C32_G(c) (c >> 10 & 0x3FF)

#define C32_B(c) (c & 0x3FF)

#define C16_R(c) (c >> 10 & 0x1F)

#define C16_G(c) (c >> 5 & 0x1F)

#define C16_B(c) (c & 0x1F)

#define PCOLOR24_TO_16(p24) (((UINT16)p24[2]&0xF8) << 8 | ((UINT16)p24[1]&0xF8) << 3 | p24[0] >> 3)

// 这几种颜色转换未实现

#define PCOLOR32_TO_16(p32) 0

#define PCOLOR16_TO_24(p16) 0

#define PCOLOR32_TO_24(p16) 0

#define PCOLOR16_TO_32(p24) 0

#define PCOLOR24_TO_32(p24) 0

// empty...

#define callerVars()

int bitblt(GdiDevice* dst, const GdiDevice* src,

int dx, int dy, int cx, int cy, int sx, int sy, BinaryOpCode op)

{

#define condition(pd, ps)

#include "template/fun_body.c"

}

int mergeblt(GdiDevice* dst, const GdiDevice* src,

int dx, int dy, int cx, int cy, int sx, int sy, BinaryOpCode op)

{

// condition no tolerance...

#define condition(pd, ps) if (pSrcToColor(ps) != src->transparentColor)

#include "template/fun_body.c"

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有