原书写于1992年,内容基于作者在Microsoft工作期间编写C语言无错代码的经验之谈,这是一本从实践总结而来的编程书籍,章节不多,但很值得一读!可惜的是,本书出版于二十年前没能与时俱进推出后续更新版本。
看的是电子版,记录下读书笔记:
你必须养成经常询问怎样编写代码的习惯,本书就是长期坚持询问一些简单问题所得的结果。
我怎样才能自动检测出错误?
我怎样才能防止错误?
这种想法和习惯是帮助我编写无错代码呢还是妨碍了我编写无错代码?
编写直观的代码才是真正的聪明人。
重要的是养成好的习惯和正确的态度。
除非关系产品的成败,否则不要整理代码 --> 这点与现在主流的重构、敏捷开发方法论背道而驰。
不要实现没有战略意义的特征
错误既不会自己产生,也不会自己改正。
不能“以后”再修改错误,这是许多产品被取消的共同教训。
修改错误要治本,不要治表
不要实现没有战略意义的特征
不允许没有必要的灵活性
测试代码的责任不在测试员身上,而是程序员自己的责
决不允许同样错误出现两次
使程序在调用点明了易懂;要避免布尔参数
关心局部效率是不值得的。如果你很注重效率的话,请集中于全局效率和算法的效率上,这样你才会看到努力的效果。
编码检查表
─一 你是否将编译程序的警告都处理了?
── 你的代码是否未用Lint
─一 你的代码进行了单元测试吗?
─一 你是否逐步通过了每一条编码路径以观察数据流?
── 是否重构过了任何代码?如果是,修改处经过彻底测试了吗?
── 程序维护人员是否能够理解你的代码?
─一 是否用断言证实了函数参数的有效性?
─一 是否使用断言警告可能出现的非常情况?
─一 代码中是否有未定义的或者无意义的代码?
─一 你在代码中是否作过任何假设?
── 代码中是否有稀奇古怪的行为?
── 代码有不必要的灵活性吗?你能消除它们吗?
─一 函数是否小并容易测试?
─一 在调用点你的函数是出易读?
─一 你的函数是否有布尔量输入?
─一 此特征是否符合产品的市场策略?
─一 是否评审了你的接口,它能保证难于出现误操作吗?
── 错误无法消失,是否能找到错误的根源?
─一 是修改了错误的真正根源,还是仅仅修改了错误的症状?
书中出现的部分代码:
1, 用户自己定义宏ASSERT的方法:
#ifdef DEBUG
void _Assert(char* , unsigned); /* 原型 */
#define ASSERT(f)
if(f)
NULL;
else
_Assert(__FILE__ , __LINE__)
#else
#define ASSERT(f) NULL
_Assert在标准错误输出设备stderr上打印一条错误消息,然后中止:
#endif
void _Assert(char* strFile, unsigned uLine)
{
fflush(stdout);
fprintf(stderr, “nAssertion failed: %s, line %un”,strFile, uLine);
fflush(stderr);
abort();
}
2, 要使用断言对函数参数进行确认。
/* memcpy ─── 拷贝不重叠的内存块 */
void* memcpy(void* pvTo, void* pvFrom, size_t size)
{
byte* pbTo = (byte*)pvTo;
byte* pbFrom = (byte*)pvFrom;
ASSERT(pvTo != NULL && pvFrom != NULL);
/* 内存块重叠吗?如果重叠,就使用memmove */
ASSERT(pbTo >= pbFrom + size || pbFrom >= pbTo + size);
while(size-->0)
*pbTo++ == *pbFrom++;
return(pvTo);
}
3,/* UnsToStr—一将无符号值转换为字符串 */
void UnsToStr(unsigned u,char *str)
{
char *strStart = str;
do {
*str++ = (u % 10) + '0';
} while((u /= 10) > 0);
*str = ' ';
ReverseStr(strStart);
}
void UnsToStr(unsigned int u, const char *str)
{
char strDigits[6];
char *pch;
/* u超出范围了吗?使用UlongToStr… */
ASSERT(u <= 65536);
pch = &strDigits[6];
*pch = ' ';
do {
*--pch = u % 10 + '0';
}while((u /= 10) > 0);
strcpy(str,pch);
}
char* strcpy(char* pchTo, const char* pchFrom)
{
char* pchStart = pchTo;
while(*pchTo++ = *pchFrom++)
NULL;
Return(pchStart);
}
4,/* memset ─── 用“byte”的值填充内存 */
void* memset(void* pv, byte b, size_t size)
{
byte* pb = (byte*)pv;
while(size-- > 0)
*pb++ = b;
return(pv);
}
/* strdup ─── 为一个字符串建立副本 */
char* strdup(const char* str )
{
char* strNew;
strNew = (char*)malloc( strlen(str)+1 );
strcpy( strNew, str );
return( strNew );
}
char* CopySubStr(char *strTo, const char* strFrom, size_t size)
{
char* strStart = strTo;
ASSERT( strTo != NULL && strFrom != NULL );
ASSERT( size <= strlen(strFrom) );
while( size-- > 0 )
strTo++ = strFrom++;
*strTo = ' ';
reurn (strStart);
}
char tolower(char ch)
{
ASSERT( ch >= ‘A’ && ch <= ‘Z’);
return( ch + ‘a’-‘A’);
}
void *memchr(void *pv, unsigned char ch, size_t size)
{
unsigned char *pch = (unsigned char *)pv;
while(size-- > 0)
{
if(*pcd == ch)
return(pch);
pch++;
}
return(NULL);
}
从实践总结而来
对“从实践总结而来”的回应
《编程精粹》热门书评
-
被人忽略的经典
17有用 1无用 codedump 2010-08-12
原文出自 codedump.info.<<编程精粹:编写高质量C语言代码>> 是一本被很多中国程序员所忽视的好书.阅读这本书的时候,我想起了另一本经典:<<程序设计实践>>., 它们有如下的共同点:1) 短小精悍, 不像一些书洋洋洒洒数百页,篇幅小保证...
-
被埋没的明珠
4有用 1无用 孙立 2009-03-25
豆瓣上竟然找不到当年的中文翻译版,可见是少人关心呀。这本书很薄,但内容深刻,每个程序员都应该看看。...
-
一本肝肠断
3有用 0无用 Jay 2011-10-30
一本谭浩强的《C语言程序设计》将一个少年引入了奇妙的C语言世界,从此为之疯狂。 之后接触的《C和指针》、《C陷...
-
从实践总结而来
3有用 0无用 Wuqifu 2012-05-30
原书写于1992年,内容基于作者在Microsoft工作期间编写C语言无错代码的经验之谈,这是一本从实践总结而来的编程书籍,章节不多,但很值得一读!可惜的是,本书出版于二十年前没能与时俱进推出后续更新版本。看的是电子版,记录下读书笔记:你必须养成经常询问怎样编写代码的习惯,本书就是长期坚持询问一些简...
-
只是小部分程序设计tricks
1有用 1无用 swq457080 2011-07-02
刚买这本书的时候对他的期望还是很高的,看完之后,有了些失望。讲思想感觉这本书不如程序员修炼之道,讲具体的编码细节不如代码大全。豆瓣评分居然有9分,感觉还是有些过的,与前面两本书的层次还是有些差距的。这本书中最独特的视角可能就是作者的那些错误代码的分析了,不过其中的例子也不是很多。第一章是用编译器预警...
书名: 编程精粹
作者: Steve Maguire
出版社: 人民邮电出版社
原作名: Writing Solid Code
副标题: 编写高质量C语言代码
出版年: 2009.2
页数: 256
定价: 45.00元
ISBN: 9787115193162