最近写书的部分内容

中山野鬼 发布于 2013/07/30 03:05
阅读 1K+
收藏 4

以下是一个模版替换的自动生成函数的部分内容,。这些代码不能直接使用,除非结合前面所有章节的内容。因为很多诸如 _Pp ,_p ,的定义,有的是宏,有的是typedef ,_sa 等是用于正向对比测试的辅助检测代码。都在这个章节之前的章节讨论。单独提出来中间一章的某一小段,是因为oscer朋友问我写了啥,我就随手抓了一把,先贴出来。只是初稿的原始稿。最终还要整理。这些将在最终书里描述的所有代码和内容都是自己写的,作为原型,也应用在我平时的设计中,没必要抄别人的。所以比较慢,毕竟自己的屎得慢慢拉,不如别人渣土车来的快捷。至于_p 我这里也贴一段定义的代码如下,能看懂_u8 p[0];的作用,并能猜出来 _P空间申请方法的,我相信这兄弟对c的指针不会跑飞,那些说c语言指针容易跑飞的人,建议要么不要这么说,要么好好练习c的基本功。

typedef struct {
//_i64 pheader[0];
_p hp;//header base p;
_I s;//size
_I t;//tail not used
_I h;//head
_I l;//len ,avail data num
_u8 p[0];//have bug if used such as BUS_S a[10];;so not allow used array mode
}_D_BUF;
typedef _D_BUF * _P;

#define _SIZE(Q) (Q)->s
#define _LEN(Q) (Q)->l
#define _HEAD(Q) (Q)->h
#define _TAIL(Q) (Q)->t
#define ___offset(m,_T_)  ((_I)(_I64)&((_T_*)0)->m)  //not support 64 index
#define _mp2SP(pv,_T_) ((_T_ *)((_p)(pv) - ___offset(p,_T_))) 

#define _Pheader(P,_T_) ((_T_*)((P)->hp))
#define _Pp(P) ((P)->p)
#define _pP(pv) _mp2SP(pv,_D_BUF)
#define _ph(p) _HEAD(_pP(p))
#define _ps(p) _SIZE(_pP(p))
#define _pt(p) _TAIL(_pP(p))
#define _pl(p) _LEN(_pP(p))
#define _pheader(p,_T_) ((_T_*)(_pP(p)->hp))

======下面是正文摘抄========

数组里面去泡泡

假设我们存在一个已知长度连续的数据单元,。而其中存在一些非法或空的单元,我们希望将这些单元去除,也即该空间连续存放有效的单元,并告知处理后数组中有效单元的数量。有多种做法可以操作,而一个通用的单次扫瞄的方式如下

#define __empty_unit(pu)

#define __cp_unit(pu,dst,src)

#define _DISCARD_UNIT(_NAME,_T_) static _I discard_##_NAME(_p p){\

_T_ *phead = (_T_ *)p;\

_T_ *ptail = (_T_ *)(p + _pl(p));\

_I w,r;\

if (phead == ptail){\

return 0;\

}\

r = 0;\

while ((!__empty_unit(phead + r))&&(phead + r < ptail)){\

r++;\

}\

w = r;\

while (phead +r < ptail){\

if (__empty_unit(phead + r)){\

r++ ;continue;\

}\

__cp_unit(phead,w,r);\

w++;\

r++;\

}\

_pl(p) -= (r - w) * sizeof(_T_);\

return w;\

}


这是一个通用的模板,通用性是靠我们使用_p这个结构类型保证的。注意对一个数组单元数量,我们并没有直接存储的地方,而是对_pl(p)的操作。为了回避获取单元数量存在除法操作的情况,实际的遍历,使用指针方式,如同你看到的phead + r等等。

对于单元的处理存在两个,一个为操作,一个为空判断。其实 这个很像c++等语言中的模板。

而在c语言中,实现方法如下

#undef __empty_unit

#undef __cp_unit

#define __empty_unit(pu) (*(pu) == 0)

#define __cp_unit(pu,dst,src) do {*(pu + dst) = *(pu + src);}while (0)

_DISCARD_UNIT(_i32,_i32)

#undef __empty_unit

#undef __cp_unit

#define __empty_unit(pu) (*(pu) == 0)

#define __cp_unit(pu,dst,src) do {*(pu + dst) = *(pu + src);}while (0)

_DISCARD_UNIT(_i16,_i16)



_i32 main(_i32 argc,_s argv[]){

init_m_alloc(0,0);

_I i;

_P P = C_MALLOC(sizeof(_i32)*100,0);

_p p= _Pp(P);

_i32 * tmp = (_i32*)p;

for (i = 0 ;i < 100 ; i++){

tmp[i] = i;

}

for (i = 0 ;i < 100 ; i++){

if (tmp[i] & 0x7){

}else{

tmp[i] = 0;

}

}

_pl(p) = sizeof(_i32) * 100;

_sa(p,_pl(p));

discard__i32(p);

_sa(p,_pl(p));

discard__i16(p);

_sa(p,_pl(p));

C_FREE(P);

return 0;

}

上面我们先申请了一个P空间,由此获取了p,通过tmp令每个空间设置值从0到100,随后我们将所有8的倍数修改为0。对应在__empty_unit的定义中,以0来做判断,该单元是否 放弃。

如果对

#undef __empty_unit

#undef __cp_unit

#define __empty_unit(pu) (*(pu) == 0)

#define __cp_unit(pu,dst,src) do {*(pu + dst) = *(pu + src);}while (0)

_DISCARD_UNIT(_i32,_i32)

看不懂,可以通过gcc -E的方式,看一下,预处理后的代码是什么内容。

这样的代码。前面两个是清除宏定义,以免重复定义。后面两个是针对_DISCARD_UNIT里的对应宏的实现。随后,直接编辑写出这个宏,则预处理程序会自动将其扩展为

static discard__i32(_p p) ....的函数。

提示:任何其他高级语言可以做的事情,C语言一样能做到,无非烦琐与否。因为c语言是最接近机器的高级语言。上述模板的调用,尽可能的不要在头文件里使用,而且尽可能的对模板扩充的函数,使用static约束。模板的价值在于确保逻辑正确性,以帮助降低编辑代码中的人为错误。很多其他高级语言所推出的时尚概念,架构、框架、协议、平台等等,对于超过15年以上的c程序员(具备足够的工程经验 和自有基础开发工具、库,模板等),重新组建一套,只是分分钟的事情。区别于其他高级语言,你需要为大量更新再学习(包括外部的类、包、开发环境等),c语言,由于主要是做基础件(平台),算法引擎,底层驱动等等因此你需要花更多的时间在逻辑分析,设计思想甚至是数学上进行研究。c的标准及标准库,linux 系统库 ,posix标准库,相应make 及衍生工具等这些知识、信息的变动,基本可以以10年为单位,每个c程序员或开发团队,更多在于自我沉淀和积累,而不是每天乐此不疲的尝试使用别人的代码资源作为自身基础。因此也可以说,c语言是一种自开发语言,其他高级语言属于应用开发语言,后者的优势就是应用系统,可以迅速实现客户应用需求,其实很多情况下,这已经足够了。

======= 结束=======

实际在案例中,是做如下设计

#define _IS_EMPTY_OP(pof) (((pof)->m ==0) && ((pof)->n== 0))

#define _CP_OP(pof,dst,src) do {\
(pof+dst)->a = (pof+src)->a;\
(pof+dst)->n = (pof+src)->n;\
(pof+dst)->b = (pof+src)->b;\
(pof+dst)->m = (pof+src)->m;\
(pof+dst)->len = (pof+src)->len;\
(pof+dst)->next = (pof+src)->next;\
}while (0)

#undef __empty_unit
#undef __cp_unit
#define __empty_unit(pu) _IS_EMPTY_OP(pu)
#define __cp_unit(pu,dst,src) _CP_OP(pu,dst,src)
_DISCARD_UNIT(op_info,_OP_FILE_S)

而不是简单的16位宽或32位宽的数组整理。但这个模版可以通用到任何类型单元,只要你能写出对应类型单元完整的判空宏和copy宏。bit除外。


补充说一下,init_m_alloc是一个空间管理的模块,在前面章节会介绍。主要用于对_P结构的空间申请,同时将空间的申请的提出者(函数名称和文件名名称)与实际空间的申请者(函数名称和文件名称)以及实际申请到的空间地址进行记录。在程序退出前,会检测,是否还有空间块没被释放,如果没有会在log和屏幕中打印,是哪些c文件对应的申请函数调用了这个模块的空间申请,但没有释放。

主要是用于空间管理使用。也不能算是对malloc做了个壳子,主要是对_P结构做了处理。我估计我会在书的第二步分,引入setjmp ,longjmp 等介绍,介绍一个系统运行,出现异常崩溃时,如何不退出,而进行自复位。其实很简单,把中断截取,然后longjmp到setjmp点,这个如果能理解,那么进程fork进程就理解了一半了。另一半是空间资源的分配问题。

加载中
0
中山野鬼
中山野鬼

引用来自“看能不能改个名”的答案

沙发. 
靠。老大,你还不睡觉。。。。。
0
ueharaai
ueharaai
痛恨free的人举下手看看。
0
中山野鬼
中山野鬼

引用来自“ueharaai”的答案

痛恨free的人举下手看看。
free有什么好痛恨的。好借好还,再借不难。痛恨free,怕是占有欲太强了。哈。
0
悟方向
悟方向
野鬼果然是名副其实  喜欢夜间出没
0
中山野鬼
中山野鬼

引用来自“享开发”的答案

野鬼果然是名副其实  喜欢夜间出没
靠。。。别提了,4点睡的,早上热也算了,给狗叫醒了。。。。郁闷。。。还热感冒了。。。。。
0
JollyRoger
JollyRoger
  路过,捧个场
0
黄开源中国
黄开源中国
支持一个。。结束前那段话表示看懂了。感谢
0
铂金小鱼
铂金小鱼
支持鬼作
黑狗
黑狗
我表示!我不知道鬼作是一个动画片和游戏!
0
八木
八木

捧场来了

返回顶部
顶部