Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 隐式转换浮点常量_C_Casting_Floating Point - Fatal编程技术网

C 隐式转换浮点常量

C 隐式转换浮点常量,c,casting,floating-point,C,Casting,Floating Point,请查看此代码: #include <stdio.h> int main(void) { short s; int i = 65696; float f = 65696.0F; printf("sizeof(short) = %lu\n", sizeof(short)); s = i; printf("s = %hd\n", s); s = f; printf("s = %hd\n", s); s = 65

请查看此代码:

#include <stdio.h>

int main(void)
{
    short s;
    int i = 65696;
    float f = 65696.0F;

    printf("sizeof(short) = %lu\n", sizeof(short));

    s = i;
    printf("s = %hd\n", s);
    s = f;
    printf("s = %hd\n", s);

    s = 65696;
    printf("s = %hd\n", s);
    s = 65696.0F;
    printf("s = %hd\n", s);

    return 0;
}  

在最后一行,为什么是32767而不是160?说
f=65696.0F有什么区别;s=f
s=65696.0F

因为如果浮点值的整数部分在新类型中不可表示,则转换是未定义的行为

在您的例子中,
SHRT_MAX
可能是32767,因此
65696.0F
的不可分割部分不能表示在
short
对象中。

这是“未定义的行为”,这意味着编译器可以自由地执行它想要的操作。但“未定义”并不意味着“无法解释”

编译器在
s=f
的情况下所做的是首先将
f
转换为
int
值65696,然后将65696赋值给s,这将溢出并留下160。编译器之所以这样做,是因为有一条CPU指令将浮点数转换为32位整数,而不是直接转换为16位整数

编译器使用
s=65696.0F
所做的工作更简单:它知道65696.0超出了范围,因此它为
s
指定了可用的最高值,即2^15-1=32767

如果读取编译器为s=f生成的汇编代码(例如,使用-s开关和gcc),则可以验证这一点:

最后一条指令对%eax的高16位进行缓冲,在本例中将其设置为所有0

它为s=65696.0F生成的内容更简单:

    movw    $32767, -10(%rbp)      # Store the lower 16 bits of 32767 into memory
    movswl  -10(%rbp), %eax        # Load those 16 bits into eax, with sign extend

+1.具体而言,6.3.1.4/1:“当实浮点型的有限值转换为除_Bool以外的整数类型时,小数部分被丢弃(即,该值被截断为零)。如果整数部分的值不能用整数类型表示,则行为未定义)”@乔恩,为什么我说f=65696.0F时,不发生同样的事情;s=f
?@rootkea这也是未定义的行为,是的,未定义的行为可能是不可预测的。@Jon所说的“有限值”是指“常数”?@rootkea它仍然是未定义的行为。在您的特定情况下,它恰好返回
160
    movss   -4(%rbp), %xmm0        # Load float from memory into register xmm0
    cvttss2si       %xmm0, %eax    # Convert float in xmm0 into signed 32 bit, store in eax
    movw    %ax, -10(%rbp)         # Store lower 16 bits of eax into memory
    movswl  -10(%rbp), %eax        # Load those 16 bits into eax, with sign extend
    movw    $32767, -10(%rbp)      # Store the lower 16 bits of 32767 into memory
    movswl  -10(%rbp), %eax        # Load those 16 bits into eax, with sign extend