原题:

4、When programmers add new elements to an enumeration, they sometimes forget to add new cases to the appropriate switch statements. How could you use assertions to help detect this problem?

附录中的答案:

.
.
.
default:
ASSERT(FALSE); /*We should never get here*/
break;

把这个问题扩展下:

看到上题的时候,想到了在u-boot中加入启动命令函数的时候曾经犯过错(还有一点,boot中的启动命令函数有点分散了,应该集中下),Z先生推荐我看下《write solid code》,无意中看了android中的源码,就有了如下的记录(非常好,以前没用过):

 //keywords.h
#ifndef KEYWORD int do_chroot(int nargs, char** args);
int do_chdir(int nargs, char** args); #define __MAKE_KEYWORD_ENUM__
/*
*定义KEYWORD宏,此处用了宏的“粘贴”预处理,此时只用到了第一个参数
*/
#define KEYWORD(symbol, flags, nargs, func) K_##symbol, enum {
K_NUKNOWN,
#endif
KEYWORD(capability, OPTION, , NULL)
KEYWORD(chdir, COMMAND, , do_chdir)
KEYWORD(chroot, COMMAND, , do_chroot) #ifdef __MAKE_KEYWORD_ENUM__
KEYWORD_COUNT,
}; #undef __MAKE_KEYWORD_ENUM__
#undef KEYWORD
#endif
 //parser.c
/*
*第一次包含keywords.h,根据keywords.h的代码,首先得到一个枚举定义.
*/
#include "keywords.h" /*
*重新定义KEYWORD宏,此处运用了宏的“#”预处理运算符
*/
#define KEYWORD(symbol, flags, nargs, func) \
[ K_##symbol ] = { #symbol, func, nargs + , flags, }, /*
*定义一个结构体keyword_info数组,它用来描述关键字的一些属性
*/
struct
{
const char *name; //关键字的名称
int (*func)(int nargs, char** args); //对应关键字的处理函数
unsigned char nargs; //参数个数,每个关键字的参数个数是固定的
unsigned char flags; //关键字的属性
}keyword_info[ KEYWORD_COUNT ] = {
[ K_UNKNOWN ] = { "unknown", , , ,},
/*
*第二次包含keywords.h,由于已经重新定义了KEYWORD宏,
*所以以前作为枚举值的关键字现在变成keyword_info数组
*的索引了.
*/
#include "keywords.h"
}; #undef KEYWORD

在parser.c中两次包含了keywords.h文件,首次包含时列出了枚举项,可以作为后文中数组的索引;第二次包含时,由于宏已被定义,因此正好可以实现数组中的各个项。

仿照此种实现,完全可以实现习题4的解答(一个枚举项对应一个相应的处理函数即可,而且可以通过索引来完成,比switch-case快);此外可以实现代码的集中管理,否则太分散了(不然就用grep,有点麻烦)。

write solid code Chapter 2 练习题4 的解答与扩展的更多相关文章

  1. write solid code 零散(原文)

    整理下目录,看了这个文件,幸好未删除. 以下是<write solid code>中的原文摘录. 1.How could I have prevented this bug? 2.How ...

  2. Code Complete 读后总结和新的扩展阅读计划

    Code Complete 读后总结和新的扩展阅读计划 用了一年时间终于将代码大全读完了,在这里做一个简单的总结,并安排下一阶段的扩展阅读计划. 1.选择代码大全作为我程序员职业入门的第一本书,我认为 ...

  3. Clean Code – Chapter 2: Meaningful Names

    Use Intention-Revealing Names The name should tell you why it exists, what it does, and how it is us ...

  4. Clean Code–Chapter 7 Error Handling

    Error handling is important, but if it obscures logic, it's wrong. Use Exceptions Rather Than Return ...

  5. Clean Code – Chapter 6 Objects and Data Structures

    Data Abstraction Hiding implementation Data/Object Anti-Symmetry Objects hide their data behind abst ...

  6. Clean Code – Chapter 5 Formatting

    The Purpose of Formatting Code formatting is about communication, and communication is the professio ...

  7. Clean Code – Chapter 4: Comments

    “Don’t comment bad code—rewrite it.”——Brian W.Kernighan and P.J.Plaugher The proper use of comments ...

  8. Clean Code – Chapter 3: Functions

    Small Blocks and Indenting The blocks within if statements, else statements, while statements, and s ...

  9. 关于write solid code中的memset

    文中说明memset可以通过操作整形以加速程序执行速度,这一点值得肯定,问题在于unicore或arm中协处理器有地址访问对齐检查,如果我们如此操作,编译器最终使用str指令来完成,那么当地址未对齐时 ...

随机推荐

  1. posix多线程--互斥量

    多线程程序在线程间共享数据时,如果多个线程同时访问共享数据就可能有问题.互斥量是解决多个线程间共享数据的方法之一. 1.互斥量初始化两种方式:(1)静态初始化 #include <pthread ...

  2. iOS-本地的推送

    // //  ViewController.m //  05-本地的推送 // //  Created by hongqiangli on 2017/6/12. // #import "Vi ...

  3. MySQL PLSQL Demo - 001.创建、调用、删除过程

    drop procedure if exists p_hello_world; create procedure p_hello_world() begin select sysdate(); end ...

  4. 解决Django中在.js文件中用ajax请求后端,找不到CSRF问题

    function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie != ...

  5. 可视化工具连接mysql报1862【mysql修改登录密码】

    1862是密码被修改了. 修改方法: 1.以root登录账户: 账户与密码都是root mysql -uroot -proot 2.修改密码 set password = password('1234 ...

  6. Ubuntu 16.04和win10双系统时间不一致解决办法

    windows10和ubuntu16.04双系统,装完后,在windows下时间不对,之前的老办法是: sudo gedit /etc/default/rcS 2 utc=yes 改成utc=no 然 ...

  7. How To Install and Configure Elasticsearch on Ubuntu 14.04

    Reference: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-elasticsear ...

  8. [app]Linux的setitimer和sleep冲突

    在Linux中使用setitimer和sleep会冲突,二者都是用信号 碰上一个头疼的问题,主程序在sleep的时候,总是被开的一个timer的signal callback所影响, 每当timer的 ...

  9. socket数据收发

    socket读写 TCP协议是面向流的,read和write调用的返回值往往小于参数指定的字节数.对于read调用,如果接收缓冲区中有20字节,请求读100个字节,就会返回20.对于write调用,如 ...

  10. 9260与SAM-BA连接(转)

    对于AT91SAM9260的bootloader的烧写,常常会遇到这样的问题:对于干净的NAND FLASH(即没有烧写过任何东西),AT91SAM9260与sam-ba很容易连接成功,但当烧写过bo ...