C 程序的输出 | 6套
预测以下程序的输出问题 1
int main()
{
unsigned int i=65000;
while ( i++ != 0 );
printf("%d",i);
return 0;
}
输出:
1
解释:
需要注意的是,while 循环体中有一个分号。因此,即使没有作为 while 主体的一部分进行任何操作,只有当不满足 while 条件时,控制才会从 while 中出来。换句话说,只要条件中的 i 变为 0,条件就会变为假并且 while 循环将结束。但也要注意 while 条件下的后增量运算符。因此,首先将 i 与 0 进行比较,无论是否满足条件, i 都会递增。由于 i 被初始化为 65000,它将继续递增,直到达到最高正值。在发生翻转之后,i 的值变为零。条件不满足,但 i 会增加,即到 1。然后 printf 将打印 1。
问题2
int main()
{
int i=0;
while ( +(+i--) != 0)
i-=i++;
printf("%d",i);
return 0;
}
输出:
-1
解释:
让我们先来看看while循环的条件。那里有几个运算符。一元 +运算符不做任何事情。所以简化的条件变成了 (i-) != 0。所以无论条件为真还是假,i 都会与 0 进行比较,然后递减。由于 i 被初始化为 0,while 的条件在第一次迭代时将为假,但 i 将递减为 -1。 while 循环体不会被执行。 printf 将打印 -1。
所以它并没有看起来那么可怕!
问题 3
int main()
{
float f=5,g=10;
enum{i=10,j=20,k=50};
printf("%d\n",++k);
printf("%f\n",f<<2);
printf("%lf\n",f%g);
printf("%lf\n",fmod(f,g));
return 0;
}
输出:
程序将无法编译并给出 3 个错误
解释:
这里,i、j 和 k 位于枚举内部,因此它们就像常量。换句话说,如果想在程序的任何地方使用 10,我们可以使用 i 代替。在第一个 printf 中,k 的值正在被修改,这是不允许的,因为它是枚举常量。在第二个 printf 中,左移运算符应用于浮点数,这也是不允许的。类似地,在第三个 printf 中,模数运算符被应用于浮点 f 和 g,这也是不允许的。
问题 4
int main()
{
int i=10;
void pascal f(int,int,int);
f(i++, i++, i++);
printf(" %d",i);
return 0;
}
void pascal f(integer :i,integer:j,integer :k)
{
write(i,j,k);
}
输出:
程序将给出编译时错误
解释:
编译器特定问题。并非所有编译器都支持这一点。
否则,pascal 强制从左到右处理参数。所以即使使用pascal可以改变参数处理顺序,我们也不能使用Pascal语言例程,例如在C程序中编写。
问题 5
void pascal f(int i,int j,int k)
{
printf("%d %d %d",i, j, k);
}
void cdecl f(int i,int j,int k)
{
printf("%d %d %d",i, j, k);
}
main()
{
int i=10;
f(i++,i++,i++);
printf(" %d\n",i);
i=10;
f(i++,i++,i++);
printf(" %d",i);
}
输出:
编译器特定问题。并非所有编译器都允许这样做。
解释:
这个问题涉及参数传递机制。如果我们调用一个函数,其中函数的参数被处理的顺序不是由C标准管辖。所以一个编译器可以从左到右处理参数,而另一个编译器可以从右到左处理它们。通常,程序不受此影响,因为程序的参数不同。例如,如果我们将函数fun 称为 fun(i, j),那么无论参数以何种顺序处理,i 和 j 的值都会保持一致。
但在这种情况下,我们使用相同的变量将参数传递给函数f。因此,在其中的参数由函数处理的顺序将确定的这些参数的值。 cdecl 强制从右到左处理参数,而 pascal 强制从左到右处理参数。
因此,第一个函数f 中的 i、j 和 k 的值将分别为 10、11 和 12,而第二个函数f 中的 i、j 和 k 的值将分别为 12、11 和 10。