本帖最后由 刘前辈 于 2011-1-17 09:57 编辑
TH0 = (- 5000 ) / 256 ; // 为什么会等于0x ED !
a = (168*196) / 10 ; // 为什么会等于0xF344!
计算机程序混了这么多年,竟然今天才弄懂,惭愧。
(-5000 )=0xec78 ;
在32位机器上表达为0xFFFFEC78,我希望的是低16位纯粹右移8位,然后取低8位,而不是要一个负数除法表达式。因此,我一定要保证是无符号数0x0000EC78 / 0x100 ; 所以应该写为:
TH0 = (unsigned )(- 5000 ) / 256 ;
// 不是强制类型 uint 什么的。概念应该不一样
而所谓诡异事件 a = (168*196) / 10 ; 应该写为:
a = ( unsigned ) (168*196) / 10 ; // 不是强制类型 (unsigned int )
这样保证0x80A0不会表达为0xFFFF80A0,—— 一个负数;造成结果诡异。
这是C语言标准中“整提升+保符号/ 保值 规则的问题。”——当一个16位的int 值最高位(符号位)为1时,它也许是表示一个负数,或许是一个经过编译器自动整提升进位上来的正数,例如:168*196= 0x80A0; 它是由int自动整提升为unsigned int 的;符号位怎么办?——这就是整提升之后运用的保符号还是保值规则;有的编译器缺省使用保符号规则(默认丢掉的符号是1——负数标识),有些编译器缺省采用保值规则 (忽略丢掉的符号,默认为0——正数标识),还有些编译器更完善,可以由用户使用编译开关来选择保值还是保符号规则。举例:0xFF, 由于符号位为1,所以既可以翻译为255d (保值规则),又可以翻译为 -1d(保符号规则),两者都是对的。究竟采用什么规则,由用户决定。
像程序医人的例子,如果希望得到正数,就可以采用采用强制unsigned 告诉编译器采用保值规则;否则,希望得到负数,就采用默认(ANSI C 默认保符号规则。),这就是为什么168*196得到一个负数的原因,也是我上面加入 unsigned 的理由。
、 |