【问题标题】:Typecasting from int,float,char,double从 int、float、char、double 进行类型转换
【发布时间】:2014-06-17 18:12:34
【问题描述】:

我尝试了几个关于类型转换的注意事项的示例。我不明白为什么下面的代码 sn-ps 无法输出正确的结果。

/* int to float */
#include<stdio.h>
int main(){
        int i = 37;
        float f = *(float*)&i;
        printf("\n %f \n",f);
        return 0;
}

这打印0.000000

/* float to short */
#include<stdio.h>
int main(){
        float f = 7.0;
        short s = *(float*)&f;
        printf("\n s: %d \n",s);
        return 0;
}

这打印7

/* From double to char */
#include<stdio.h>
int main(){
        double d = 3.14;
        char ch = *(char*)&d;
        printf("\n ch : %c \n",ch);
        return 0;
}

这会打印垃圾

/* From short to double */
#include<stdio.h>
int main(){
        short s = 45;
        double d = *(double*)&s;
        printf("\n d : %f \n",d);
        return 0;
}

这打印0.000000

为什么从floatint 的转换会给出正确的结果,而在显式转换类型时所有其他转换都会给出错误的结果?

我无法清楚地理解为什么需要这种(float*) 的类型转换而不是float

int i = 10;
float f = (float) i; // gives the correct op as : 10.000

但是,

int i = 10;
float f = *(float*)&i; // gives a 0.0000

以上两种类型转换有什么区别?

为什么我们不能使用:

float f = (float**)&i;
float f = *(float*)&i;

【问题讨论】:

  • float f = (float)&amp;i不把i的内存位置分配给f吗?
  • 您正在转换指针,而不是数值,这意味着您正在处理一种类型的对象(例如int好像它们是另一种类型的对象(如float)。结果是垃圾。要转换数值,只需使用int i = 37; float f = i; -- 或者,如果您坚持不必要地明确,请使用float f = (float(i);。 (所有数字类型都可以隐式转换,因此很少需要从一种数字类型转换为另一种。)(float 的范围和精度要求不能像 16 位那样窄。)跨度>

标签: c casting


【解决方案1】:

在这个例子中:

char ch = *(char*)&amp;d;

您没有从double 转换为char。您正在从double* 转换为char*;也就是说,您正在从一个双 指针 转换为一个字符 指针

C 将在转换值时将浮点类型转换为整数类型,但由于您将指针转换为这些值,因此没有进行转换。你会得到垃圾,因为浮点数与定点数的存储方式非常不同。

【讨论】:

    【解决方案2】:

    了解浮点数在系统中的表示。它不是你期望的那样。在您的第一个 sn-p 中通过(float *) 进行转换,读取最重要的前 16 位。如果你的系统是小端的,如果 int 类型变量中包含的值小于 2^16,则最高有效位将始终为零。

    【讨论】:

    • 同样,它因系统而异。
    • 是的,确实如此——但您的回答没有提到这一点。第一个 sn-p int i = 37; float f = *(float*)&amp;i;*doesn't* 读取最高有效位或前 16 位;它尝试从int 对象中读取CHAR_BIT * sizeof (float) 位。
    【解决方案3】:

    如果需要将int转换为float,直接转换,因为C的提升规则。
    所以,写就够了:

        int i = 37;
        float f = i;
    

    这给出了结果f == 37.0

    但是,在转换 (float *)(&amp;i) 中,结果是一个“指向浮点的指针”类型的对象。
    在这种情况下,“整数指针”&i 的地址与“浮点指针”(float *)(&i) 的地址相同。但是,最后一个对象指向的对象是float,其位与对象i 相同,后者是一个整数。

    现在,本次讨论的重点是内存中对象的位表示对于整数和浮点数非常不同。
    正如其二进制数学表达式所指示的那样,正整数以显式形式表示。
    但是,浮点数有其他表示,包括尾数和指数。

    所以,一个对象的位,当解释为一个整数时,有一个含义,但相同的位,解释为一个浮点数,有另一个非常不同的含义。

    【讨论】:

      【解决方案4】:

      更好的问题是,为什么它永远有效。你看,当你这样做时

      typedef int T;//replace with whatever
      typedef double J;//replace with whatever
      T s = 45;
      J d = *(J*)(&s);
      

      您基本上是在告诉编译器(获取 s 的 T* 地址,将它指向的内容重新解释为 J,然后获取该值)。实际上没有发生值的转换(更改字节)。有时,幸运的是,这是相同的(低值浮点数的指数为 0,因此整数解释可能相同)但通常情况下,这将是垃圾,或者更糟糕的是,如果大小不同(就像从 char 转换为 double 一样)您可以读取未分配的数据(堆损坏(有时)!)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多