1. 由于浮点数表示的精度有限,浮点运算是不可结合的。例如,在大多数机器上,C表达式 ( 3.14 + 1e20 ) - 1e20求得的值会是0.0,而 3.14 + ( 1e20 - 1e20 )求得的值会是3.14
2. 因为32位机器在过去20年里一直是标准,许多程序的编写都是以典型的32位机器列出的分配原则为假设的。在不久的将来,随着64位机器越来越重要,在将这些程序移植到新机器上时,许多隐藏的对字长的依赖就会显现出来,成为错误。比如,许多程序员假设一个声明为int类型的程序对象能被用来存储一个指针。这在大多数32位机器上工作正常,但在一台Alpha机器上却会导致问题。
3. little endian: 最低有效字节在最前面的方式
big endian: 最低有效字节在最后面的方式
4. 环
对于整数集合Z,有一个环<Z,+,*,-,0,1>
对于布尔代数,<{0,1},|,&,~,0,1>
void swap( int& x, int& y )
{
x = x ^ y;
y = x ^ y;
x = x ^ y;
}
利用环的属性来达到效果,每个元素就是它自身的加法逆元
5. 逻辑运算
x == y <==> !( x ^ y )
6. 移位
逻辑右移和算术右移,C标准并没有明确定义应该使用哪种类型的右移。对于无符号数据(以unsigned 限定),右移必须是逻辑的。而对于有符号数,算术和逻辑的都是可以的。但,这就意味着任何一种或者另一种右移形式的代码都潜在地会遇到可移植性问题。然而,实际上,几乎所有的编译器/机器组合都对有符号数使用算术右移,且许多程序员也都假设使用这种右移。
7. 补码
C的标准并没有要求要用二进制补码形式来表示有符号整数,但是几乎所有的机器都是这么做的。为了保证代码的可移植性,我们不应假设任何可表示的数值范围,或者假设它们会被如何表示。C库中的文件<limits.h>定义了一组常量,来限定运行编译器的这台机器的不同数据类型的范围。
当执行一个运算时,如果它的一个运算数是有符号的而另一个是无符号的,那么C会隐含地将有符号的参数强制转换为无符号的数,来执行这个运算,但是这对于像<和>这样的关系运算符来说,它会导致与直觉不相符的结果。例如,-1 < 0U,因为在执行这个运算时,会首先将-1变为无符号数2^32-1,这样显然运算返回false。
P50