编程之规范(一)

转自:http://blog.sina.com.cn/s/blog_5e8facd20100eorv.html

一个函数,完成内存移动,并为其写一个简单的测试用例来进行测试。

   够简单的吧?有的同学很快就写出了答案,详见程序清单1与程序清单2。  

程序清单 1   V0.1版程序

void MyMemMove(char *dst,char *src,int count)

{

    while(count--)

    {

        *dst++ = *src++;

    }

}

 

程序清单 2   测试用例

void Test()

{

    char p1[256] = ”hello,world!”;

    char p2[256] = {0};

    MyMemMove(p2,p1,strlen(p1));

    printf(“%s”,p2);

}

    客观地讲,相比那些交白卷或者函数声明都不会写的同学来说,能够写出这段代码的同学已经非常不错了,至少在C语

言这门课程上已经达到了现行高校的教育目标,但是离企业的用人要求还有一定的距离。我们不妨将上面的程序称为V0.1

版本,看看还有没有什么地方可以改进。

    首先我们看看函数声明是否合理,V0.1版的程序将源地址和目的地址都用char *来表示,这样当然也没有什么问题,但

是让其他人使用起来却很不方便,假如现在要将count个连续的结构体对象移动到另外一个地方去,如果要使用v0.1的程序

的话,正确的写法如下:

     MyMemMove((char *)dst,(char *)src,sizeof(TheStruct)*count)

    也就是说我们需要将结构体指针强制转换成char * 才能够正常工作,这样除了字符串以外其它的类型都不可避免地要

进行指针强制转换,否则编译器就会呱呱叫,比如在VC++2008下就会出现这样的错误:

    error C2664: 'MyMemMove' : cannot convert parameter 1 from 'TheStruct *' to 'char *'

    那么如何解决这个问题呢?其实很简单,我们知道有一种特别的指针,任何类型的指针都可以对它赋值,那就是void *,所以应该将源地址和目的地址都用void*来表示。当然函数体的内容也要作相应的改变,这样我们就得到了V0.2版的程序。

 

程序清单 3   V0.2版程序

void MyMemMove(void *dst,void *src,int count)

{

     while (count--)

     {

        *(char *)dst = *(char *)src;

        dst = (char *)dst + 1;

        src = (char *)src + 1;

      }

}

    有的同学可能会问,这里面不是还有指针强制转换吗?只不过是换了地方。没错,强制指针转换确实是从使用者的代码转移到了库的代码里,但我们可以将MyMemMove理解为库,而将Test理解为使用者,事实上通过调整之后的效果却有天壤之别,V0.1是一逸永劳,而V0.2是一劳永逸!

    还有几个细节需要注意,为了实现链式表达式,我们应该将返回值也改为void *。此外,如果我们不小心将“*(char *)dst = *(char *)src;”写反了,写成“*(char *)src = *(char *)dst;”编译照样通过,而为了找出这个错误又得花费不少时间。注意到src所指向的内容在这个函数内不应该被改变,所有对src所指的内容赋值都应该被禁止,所以这个参数应该用const修饰,如果有类似的错误在编译时就能够被发现:

    error C3892: 'src' : you cannot assign to a variable that is const

    作为程序员犯错误在所难免,但是我们可以利用相对难犯错误的机器,也就是编译器来降低犯错误的概率,这样我们就得到了V0.3版的程序。

 

程序清单 4  V0.3版程序

void * MyMemMove(void *dst,const void *src,int count)

{

    void *ret=dst;

    while (count--)

    {

        *(char *)dst = *(char *)src;

        dst = (char *)dst + 1;

        src = (char *)src + 1;

     }

     return ret;

}

#include<stdio.h>
void *MyMemMove(void *dst,const void *src,int count)
{
    void* ret=dst;
	while(count--)
	{
		*(char *)dst=*(char *)src;//(char *)是强制转化的。

		dst=(char *)dst+1;
		src=(char *)src+1;
	}
	return ret;
}
void Test()
{
   char p1[256]="hello,world!";
   char p2[256]={0};
   MyMemMove(p2,p1,strlen(p1));
   printf("%s\n",p2);
}
int main()
{
	Test();
         return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值