(转)一段代码的几种写法-怎么样写好的代码
2010-09-24 16:01
260 查看
程序员当然要说代码了,代码是程序员的一切,离了代码说其他都是假的,我这里从一段代码开始。
int c=0, n=0,nDiff=0;
int height = m_imgHeight;//image height
LPBYTE lpDsp = pSampling;
jp2_int16 *sp, val;
LPBYTE dest;
//m_imgWidth-image width
nDiff = m_lineBytes - m_imgWidth*3;
while (height--) {
for (c=0; c<THREE_COMPONENT; c++) {
dest = lpDsp+c;
sp = m_lines[c].m_pBuf;
for (n=m_imgWidth; n>0; n--, sp++, dest+=THREE_COMPONENT) {
*sp += 2;//virtual option
……
*dest = *sp;
}
}
/*
If the bytes isn't 4-bytes multiple, 1-3 bytes will not be
initialized. So these bytes should be initialized as 0
*/
if(nDiff){
dest -= 2;
for(n = nDiff;n>0;n--){
*dest = 0;
dest++;
}
}
lpDsp += m_lineBytes;
}
这段代码的目的是一个与图形相关的操作,这里省略了许多代码,所以不可能编译;其基本的含义是从一个缓冲区复制到目标缓冲区pSampling。其中m_imgWidth和m_imgHeight表示图象的宽度和高度,m_lineBytes表示4个字节对齐的一行像素的字节数。
我们知道BMP文件的像素要求每行的最终字节数必须是4个倍数。如果图象宽度是4的倍数,不用仇是没有问题的;如果不是4的倍数,例如:129,而且每个像素一个字节,那么最终存储的长度是132个字节,但后面的几个字节如果不填充是未知的内容。上面if(nDiff){后面的就是为了填充这些多余的字节。
我的一个朋友认为这样写更有效一点:
dest -= 2;
for(n = nDiff;n>0;n--){
*dest = 0;
dest++;
}
他的分析是:如果66%的机会nDiff不是0,这个代码效率更高。
来看一下两种写法的不同:
第一种写法是:不管3721,都判断一下;如果nDiff不为0,需要至少3个指令:判断/减/判断。
第二种写法是:不判断,先减,然后通过for循环来判断。对于nDiff为0不为0,都是两个指令:减/判断。
但如果多余66%的机会(比如70%)nDiff不为0,第一种写法需要的平均指令数为:
70%*3+30%*1 = 2.4
第二种写法的平均指令数为:
70%*2+30%*2 = 2
可见第二种写法的好处可以体现在:
1. 代码简洁
2. 效率更高
但我发现代码中很少的机会nDiff不为0,这位老兄又立刻想到了另一种写法:
if(nDiff){
dest -= 2;
do{
*dest = 0;
dest++;
} while(nDiff--);
}
再来看一下这种写法的特点,假设30%的机会nDiff不为0:
原来写法的指令数为:
70%*1+30%*3 = 1.6
上面写法的指令数为:
70%*1+30%*2 = 1.3
因为第一次不需要判断;当然后面的循环都是一样的。
从这件事情的本身我们甚至可以说是吹毛求茨,而从效率上来说这个代码提高的并不是很多。但我想说的不是这些,而是故事说明的写这个代码的时候作者在想些什么,我想至少是这样的:
1. 写出简洁的代码。第二种写法明显简洁。
2. 写出最高效的代码,即使是CPU很快的今天。如果上面的代码在一个循环的内部,效率高低很快就体现出来。
3. 深入的思考和比较。计算条件成立的概率,至少应该对代码在什么情况下运行很了解。
4. 写好代码的精神。
int c=0, n=0,nDiff=0;
int height = m_imgHeight;//image height
LPBYTE lpDsp = pSampling;
jp2_int16 *sp, val;
LPBYTE dest;
//m_imgWidth-image width
nDiff = m_lineBytes - m_imgWidth*3;
while (height--) {
for (c=0; c<THREE_COMPONENT; c++) {
dest = lpDsp+c;
sp = m_lines[c].m_pBuf;
for (n=m_imgWidth; n>0; n--, sp++, dest+=THREE_COMPONENT) {
*sp += 2;//virtual option
……
*dest = *sp;
}
}
/*
If the bytes isn't 4-bytes multiple, 1-3 bytes will not be
initialized. So these bytes should be initialized as 0
*/
if(nDiff){
dest -= 2;
for(n = nDiff;n>0;n--){
*dest = 0;
dest++;
}
}
lpDsp += m_lineBytes;
}
这段代码的目的是一个与图形相关的操作,这里省略了许多代码,所以不可能编译;其基本的含义是从一个缓冲区复制到目标缓冲区pSampling。其中m_imgWidth和m_imgHeight表示图象的宽度和高度,m_lineBytes表示4个字节对齐的一行像素的字节数。
我们知道BMP文件的像素要求每行的最终字节数必须是4个倍数。如果图象宽度是4的倍数,不用仇是没有问题的;如果不是4的倍数,例如:129,而且每个像素一个字节,那么最终存储的长度是132个字节,但后面的几个字节如果不填充是未知的内容。上面if(nDiff){后面的就是为了填充这些多余的字节。
我的一个朋友认为这样写更有效一点:
dest -= 2;
for(n = nDiff;n>0;n--){
*dest = 0;
dest++;
}
他的分析是:如果66%的机会nDiff不是0,这个代码效率更高。
来看一下两种写法的不同:
第一种写法是:不管3721,都判断一下;如果nDiff不为0,需要至少3个指令:判断/减/判断。
第二种写法是:不判断,先减,然后通过for循环来判断。对于nDiff为0不为0,都是两个指令:减/判断。
但如果多余66%的机会(比如70%)nDiff不为0,第一种写法需要的平均指令数为:
70%*3+30%*1 = 2.4
第二种写法的平均指令数为:
70%*2+30%*2 = 2
可见第二种写法的好处可以体现在:
1. 代码简洁
2. 效率更高
但我发现代码中很少的机会nDiff不为0,这位老兄又立刻想到了另一种写法:
if(nDiff){
dest -= 2;
do{
*dest = 0;
dest++;
} while(nDiff--);
}
再来看一下这种写法的特点,假设30%的机会nDiff不为0:
原来写法的指令数为:
70%*1+30%*3 = 1.6
上面写法的指令数为:
70%*1+30%*2 = 1.3
因为第一次不需要判断;当然后面的循环都是一样的。
从这件事情的本身我们甚至可以说是吹毛求茨,而从效率上来说这个代码提高的并不是很多。但我想说的不是这些,而是故事说明的写这个代码的时候作者在想些什么,我想至少是这样的:
1. 写出简洁的代码。第二种写法明显简洁。
2. 写出最高效的代码,即使是CPU很快的今天。如果上面的代码在一个循环的内部,效率高低很快就体现出来。
3. 深入的思考和比较。计算条件成立的概率,至少应该对代码在什么情况下运行很了解。
4. 写好代码的精神。
相关文章推荐
- js中if语句的几种优化代码写法
- 关于解决导出Excel乱码的几种代码写法
- 你写过的一段最厉害的代码是怎么样的?
- (2)你写过的一段最魔性的代码是怎么样的?
- js中if语句的几种优化代码写法
- 怎么样写一段高效,安全的sql查询代码
- 怎么样写一段高效,安全的sql查询代码
- 你写过的一段最魔性的代码是怎么样的?
- 代码优化,怎么样写好代码
- (3)你写过的一段最魔性的代码是怎么样的?
- 怎么样写一段高效,安全的sql查询代码
- 怎么样写一段高效,安全的sql查询代码---(很基础,但是大家很容易忽略的)
- js中if语句的几种优化代码写法
- 一段方法内部递归代码的写法
- #ifdef __cplusplus extern "C" { #endif //一段代码 #ifdef __cplusplus } #endif 解读
- //比较实用的一段代码,单击鼠标并在单击位置创建物体的功能
- 交换函数几种写法
- C语言中将三个数字进行排序的几种写法
- 一段追妹妹的Java代码,好经典
- 论一段简单的代码的更改