对《Windows程序设计》的疑惑

8 篇文章 0 订阅
7 篇文章 0 订阅

bmch.bcWidth * bmc h.bcBitCount bmch.bcWidth * bmc h.bcBitCount 前几天在书上看到

	iWidthBytes = 2 * ((cx * cBitsPixel + 15) / 16) ; 
	iWidthBytes = (cx * cBitsPixel + 15) & ~15) >> 3 ;

两句话 刚开始很是疑惑,不明白为什么下面一语句和上面语句有相同的结果。通过到处查资料,终于明白了。

    用通俗的话说,两语句的结果都是最靠近(cx * cBitsPixel)的并且大于本身的16的倍数。例如,(cx * cBitsPixel)为20,那么iWidthBytes为32。大家应该都知道第一个语句为什么是乘以2再除以16,而不是直接除以8,为的是使iWidthBytes恒为偶数。

    现在说下面一句。下面的语句看起来复杂些,运用到了逻辑运算符,我们慢慢来了解。我们暂时把(cx * cBitsPixel)看成cBytes。先看看为什么要加15,这就好像四舍五入一样,只不过它都是向上入的,也就是说,得到的值必须比自身大,在C语言中,我们要把一个数四舍五入时,通常是这样写的( int)( iNumber + 0.5)(假设 iNumber是浮点型)。因为把一个数字强制转换成int类型,机器只是简单把小数抛掉,并没有达到四舍五入的效果。我们回到原来的语句,当cBytes+15时,是为了是它向上靠近,这样说可能不准确,但是它的效果和( int)( iNumber + 0.5)中的0.5是一样的。我们以( cBytes = 20)为例,假设现在在一台16位的电脑上运行语句,看为2进制码,20也就是 0000 0000 0001 0100,我们加上15( 0000 0000 0000 1111),等于35( 0000 0000 0010 0011),然后再与~15( 0111 1111 1111 0000),我们就得到
32( 0000 0000 0010 0000),最后在 >> 3,就得出4( 0000 0000 0000 0100),也就是字节数。
今天在书上又看到了类似的语句
 RowLength = 4 * ((bmch.bcWidth * b mch.bcBitCount + 31) / 32) ;  	
	RowLength = ((bmch.bcWidth * bmc h.bcBitCount + 31) & ~31) >> 3  ;

顿时又傻眼了,因为后面加的数变成了31。然后我把这两组语句拿来对比,并结合书上的提示,应该算是弄得个明白了。
对于第一组语句,书上说的是,为了使iWidthBytes总是偶数;对于第二组语句,书上说的是,为了使RowLength总是4的倍数。我才发现我原来有个地方想错了,原以为2 * ((cx * cBitsPixel + 15) / 16)这个语句中的2 * ()只是为了把iWidthBytes变成2的倍数,而忽略了括号里的15。今天才明白为什么,还是和我上面说的一样,现在补充一点:
cx * cBitPixel 后面加的那一个数,是根据要得到多少个字节数的倍数而定的,后面那一个要除的数,可以拆成8 * 因子,上面那种写法是根据整型计算的特性(把小数截掉)得出的。之所以括号里写的是(字节 * 倍数 * 8 - 1),想想四舍五入就可以知道,那十进制来说,假如我们要把1.5向上入,那么可以写成int(1.5 + 0.9),我们还知道1向上入,就是它本身,所以如果我们加的是1,而不是0.9,那么1向上入后就会变成2,这就错了。
以上是我的对这个疑惑的解释,如果有说得不对的,欢迎指出!
------------------------------------------------------
无意间翻看到以前写的这篇blog,发现存在问题,这里纠正一下。
当(cx * cBitsPixel)为20,iWidthBytes并不为32,而是4。假设(cx * cBitsPixel) + 15为X,那么16 * n <= X < 16 * (n + 1),n是整数,所以X / 16的结果是n。最后乘上2,也就是iWidthBytes的值,为2n,换句话说就是总是2的倍数。然后,对于使用位操作符计算的方式,仍然用上面的假设,一定有16 * n = X & ~15,然后通过>>3计算出字节数。至于为什么一定是2的倍数,X & ~15的低4位是0,那么在>>3之后,第0位一定是0,所以肯定是2的倍数。对于第二组语句,可以使用类似的方法理解。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值