【整理】C语言编程精粹

来源:互联网 发布:html引用javascript 编辑:程序博客网 时间:2024/04/29 06:25

以下内容整理自《C语言编程精粹》一书。

 

项目中遇到并解决一个错误后要做如下总结:

1. 怎样才能自动的勘察出这个错误

2. 怎样才能避免这个错误

 

假想存在完美的编译器,编写代码的过程中处理所有你期待这个完美编译器能检查出的错误。

例如:写了如下语句strCopy = memcpy(malloc(length), str, length);

因为我们期望在这条语句出错时,我们假想的完美的编译器能够给出:“Invalid argument: memcpy failswhen malloc returns NULL”的提示。

所以,我们要在代码中自己来对这条语句进行出错处理。例如:

if (malloc(length))

{

      strCopy = memcpy(malloc(length), str, length);

}

else

{

      printf(“Invalid argument: memcpy fails when malloc returns NULL”);

      abort(0);

}

 

故意写一条空语句后最好让“;”独占一行,例如:

if (0 == i)

;

else

...

 

设计函数原型的时候尽量采用“增强”的函数原型,例如:

将函数原型void*memchr(const void* pv, int ch, int size);

增强设计为void*memchr(const void* pv, unsigned char ch, size_t size);

这样,在调用函数时,如果程序员弄错了ch和size的顺序,编译器就能给出警告消息。

 

将调试代码隐藏在assert中,例如将:

void memcpy(void* pvTo, void* pvFrom, size_tsize)

{

    void*pbTo = (byte*)pvTo;

    void*pbFrom = (byte*)pvFrom;

    #ifdefDEBUG

    if(pvTo== NULL | | pvFrom == NULL)

    {

        fprintf(stderr,“Bad args in memcpy/n”);

        abort();

    }

    #endif

    while(size-->0)

        *pbTo++== *pbFrom++;

    return(pvTo);

}

改善为:

void memcpy(void* pvTo, void* pvFrom, size_tsize)

{

    void*pbTo = (byte*)pvTo;

    void*pbFrom = (byte*)pvFrom;

    assert(pvTo!= NULL && pvFrom != NULL);

    while(size-->0)

        *pbTo++== *pbFrom++;

    return(pvTo);

}

再进一步改善为:

/* memcpy ─── 拷贝不重叠的内存块 */

void memcpy(void* pvTo, void* pvFrom, size_tsize)

{

    void*pbTo = (byte*)pvTo;

    void*pbFrom = (byte*)pvFrom;

    ASSERT(pvTo!= NULL && pvFrom != NULL);

    ASSERT(pbTo>=pbFrom+size|| pbFrom>=pbTo+size);

    while(size-->0)

        *pbTo++== *pbFrom++;

    return(pvTo);

}

注:assert是个只有定义了DEBUG才起作用的宏,如果其参数的计算结果为0,就中止调用程序的执行。

 

可以重定义assert,例如:

#ifdef DEBUG

    void_Assert(char* , unsigned);     /* 原型 */

#define ASSERT(f)           /

    if(f)                       /

        NULL;               /

    else                        /

        _Assert(__FILE__, __LINE__)

#else

    #defineASSERT(f)           NULL

#endif

 

_Assert在标准错误输出设备stderr上打印一条错误消息,然后中止:

void _Assert(char* strFile, unsigned uLine)

{

    fflush(stdout);

    fprintf(stderr,“/nAssertion failed: %s, line %u/n”,strFile, uLine);

    fflush(stderr);

    abort();

}

在执行abort之前,需要调用fflush将所有的缓冲输出写到标准输出设备stdout上。

 

 

 

 

 

 

 

原创粉丝点击