1. 输出各种整数类型的变量
输出不同类型的整数,需要使用不用的格式限定符。输出 Unsigned Int 类型的整数,要用 %U。输出 Long ,要用 %Ld;如果要以十六进制或者八进制形式输出,那就用 %Lx(或者%LX)或者 %Lo。注意:虽然整数常量的后缀使用大写或者小写英文字母都没关系,但是它们格式限定符必须使用小写!如果我们要输出 Short 类型的整数,可以在 %D 中间加上前缀 H,也就是%Hd;同理,%Ho 和 %Hx(或者 %HX )分别表示以八进制或十六进制形式输出。前缀 H 和 L 可以和 U 组合,表示输出无符号整数。例如:%Lu 表示输出 Unsigned Long 类型的整数;%Hu 表示输出Unsigned Short类型的整数。如果您的编译器支持C99,可以使用 %Lld 和 %Llu 分别表示输出 Long Long 和 Unsigned Long Long 。下面我们来看一个输出各种类型整数的程序:
#Include <Stdio.H>
Int Main(Void)
{
Unsigned Int Un = 3000000000; /* 我使用的编译器 Int 是 32 位的 */
Short End = 200; /* 而 Short 是 16 位的 */
Long Big = 65537;
Printf("Un = %U And Not %D
", Un, Un);
Printf("End = %Hd And %D
", End, End);
Printf("Big = %Ld And Not %Hd
", Big, Big);
Printf("Press ENTER To Quit...");
Getchar();
Return 0;
}
使用 Dev-C++ 编译运行这个程序输出结果如下:
Un = 3000000000 And Not -1294967296
End = 200 And 200
Big = 65537 And Not 1
Press ENTER To Quit...
这个程序表明,错误使用格式限定符会导致意想不到的输出。首先,错误使用 %D 来做无符号整型变量 Un 的格式限定符,导致输出的是负数。这是因为我的计算机使用相同的二进制形式来表示 3000000000 和 -129496296 ,而计算机只认识二进制。所以,如果我们使用 %U 告诉 Printf 输出无符号整数,输出的就是 3000000000;如果我们误用了 %D,那么输出的就是一个负数。不过,如果我们把代码中的 3000000000 改成 96 的话,输出就不会出现异常。因为 96 没有超出 Int 的表示范围。
然后,对于第二个 Printf,无论我们使用 %Hd 还是 %D,输出的结果都是一样的。这是因为 C 语言标准规定,当 Short 类型值传递给函数时,要自动转化成 Int 类型值。之所以转化成 Int,是因为 Int 被设计为计算机处理效率最高的整数类型。所以,对于 Short 和 Int 大小不同的计算机来说,把变量 End 转化成 Int 类型再传递给函数,速度更快。如此说来,H 好像没有存在意义。其实不然。我们可以用 %Hd 来看看较大的整数类型被截断成 Short 类型的时候会是什么样的。
而第三个 Printf,由于误用 %Hd,导致输出是 1。这是因为,如果 Long 是 32 位的话,65537 的二进制形式便是 0000 0000 0000 0001 0000 0000 0000 0001,而 %Hd 命令 Printf 输出 Short 类型的值,从而导致 Printf 只处理 16 位数据(假设 Short 是 16 位的),最终导致输出 1。
在前面的教程里,我们说过,保证格式限定符的数目和参数数目一致是我们的责任。同样,保证格式限定符的类型和参数类型一致也是我们的责任!正如上面所说的那样,错误使用格式限定符会导致意想不到的输出!标准规定,如果任意参数和与其对应的格式限定符类型不一致,则 Printf 的行为是未定义的;如果格式限定符本身就是非法的,则 Printf 的行为也是未定义的。
2. 整数溢出
首先请看以下程序:
#Include <Stdio.H>
Int Main(Void)
{
/* 32 位 Int 表示范围的上限和下限 */
Int I = 2147483647, J = -2147483648;
Unsigned Int K = 4294967295, L = 0;
Printf("%D %D %D %D
", I, I+1, J, J-1);
Printf("%U %U %U %U %U
", K, K+1, K+2, L, L-1);
Printf("Press ENTER To Quit...");
Getchar();
Return 0;
}
使用 Dev-C++ 编译运行这个程序输出结果如下:
2147483647 -2147483648 -2147483648 2147483647
4294967295 0 1 0 4294967295
Press ENTER To Quit...
本例中,I+1 是负数,J-1 是正数,K+1 是 0,L-1 是 4294967295 。这是因为加减运算过后,它们的值超出了它们对应的那种整数类型的表示范围,我们把这种现象称为溢出。
Unsigned Int 型变量的值如果超过了上限,就会返回 0,然后从 0 开始增大。如果低于下限,那么就会到达 Unsigned 型的上限,然后从上限开始减小。就好像一个人绕着跑道跑步一样,绕了一圈,又返回出发点。一般,Int 型变量溢出的话,会变成负数,或者正数。
对于 Unsigned 类型的整数,它们溢出时的情况一定和上面描述的一样,这是标准规定的。但是标准并没有规定有符号整数溢出时会出现什么情况。这里描述的有符号整数溢出时出现的情况是最常见的,但是在别的计算机,使用别的编译器,也可能出现不同的情况。 |