1

我正在阅读这个问题。阅读第一个答案后,我无法理解-5 >> 1 = -3. 我还围绕它进行了更多调整。

您还可以在此处查看代码和输出。这是我所做的:

#include<stdio.h>

int main(){

printf("5/2 = %d\n",5/2);
printf("5 >> 1 = %d\n",5 >> 1);
printf("5/2 = %lf\n",5/2);
printf("5 >> 1 = %f\n",5 >> 1);
printf("-5/2 = %d\n",-5/2);
printf("-5 >> 1 = %d\n",-5 >> 1);
printf("-5/2 = %f\n",-5/2);
printf("-5 >> 1 = %f\n",-5 >> 1);

return 0;
}

输出 :

5/2 = 2
5 >> 1 = 2
5/2 = 2.168831
5 >> 1 = 2.168831
-5/2 = -2
-5 >> 1 = -3
-5/2 = 2.168833
-5 >> 1 = 2.168833

我无法理解5/2 == 2.168831, 5 >> 2 == 2.168831, 5 >> 1 == -3

为什么会这样? (答案可能非常基本,我错过了一些基本的东西,所以请指导我)。

4

2 回答 2

9

的结果-5 / 2是 a int,而不是 afloat或 a double。但是,您的格式说明符是%f,因此您int解释为 a float,这是没有意义的,因此值不稳定。您正在做的事情称为未定义行为:任何事情都可能发生。

于 2013-01-13T10:32:18.330 回答
3

你看到你所做的结果的原因是:

当您传递一个int参数但使用 printf 说明符 for double(请记住,在这种情况下 afloat被转换为 a double),然后大多数 C 实现int根据它们将int参数传递给可变参数函数(一个接受不同参数类型),但printf例程将机器状态解释为好像传递了一个double参数,如下所述。(这不一定总是发生;一旦您离开了 C 标准定义的行为,C 实现可能会做其他事情。特别是,可能会与优化器进行复杂的交互,从而导致令人惊讶的结果。然而,这就是发生的事情最常见的。你不能依赖它。)

每个计算平台都有一些关于如何传递参数的规则。一个平台可能会指定将所有参数从右到左推入堆栈,并且每个参数仅使用所需的字节数放入堆栈。另一个平台可能会指定从左到右将参数推入堆栈,或者将参数填充到下一个四个字节的倍数,以保持堆栈良好对齐。许多现代平台规定,一定大小以下的整数参数在通用寄存器中传递,浮点参数在浮点寄存器中传递,其他参数在堆栈中传递。

printf看到%f并寻找一个double参数,但你已经通过了一个intprintf找到什么?如果此平台将两个参数都推入堆栈,然后printf找到您的位int,但它会将这些位解释为好像它们是double. 这导致printf打印一个由 your 确定的值int,但它与 your 没有明显关系,因为这些位在 for和 forint的编码中具有完全不同的含义。intdouble

如果这个平台把一个int论点放在一个地方,而把一个double论点放在另一个地方,那么会发现一些与你的论点printf完全无关的部分。int它们是恰好遗留在例如double参数应该所在的浮点寄存器中的位。这些位只是以前工作的残余。相对于int您通过的值,您获得的值基本上是随机的。您还可以通过获取您传递的 4 个字节以及附近其他任何内容的 4 个printf字节来查找 a 的 8 个字节。doubleint

当您多次运行该程序时,您通常会看到打印相同的值。发生这种情况有两个原因。首先,计算机是机械的。它们在很大程度上以确定性的方式运行,因此它们一遍又一遍地做同样的事情,即使这些事情并不是特别设计为按照您使用它们的方式使用。其次,操作系统在启动时传递给程序的环境在每次启动程序时基本相同。它的大部分内存要么被清除,要么从程序文件中初始化。一些内存或其他程序状态是从计算机中的其他环境初始化的。该数据可能因程序的运行而异。例如,当前时间明显地从运行到运行变化。您的命令历史记录也是如此,加上命令外壳放置在其环境变量中的值。有时多次运行一个程序会产生不同的结果。

When you use code whose behavior is not defined by some specification (which may be the C specification, a compiler specification, a machine and operating system specification, or other documents), then you cannot rely on the behavior of that code. (It is possible to rely on the behavior of code compiled by a particular C compiler that is specified by that C compiler even though it is not fully specified by the C standard.)

于 2013-01-13T12:17:01.433 回答