问题_001_数据类型转换

一. 问题的描述 ===》

 

二. 解题的思路 ===》

  1. char a = 'a'; ---> 将字符'a'的值赋值个一个叫"a"的character类型的变量。

  2. int i = 3, j = 5; ---> 将整数形式的3和5赋值给名叫"i","j"的变量。

  3. 表达式 a = a + i, a + j; (今日主角) ---> 沉着分析、冷静分析,嘶...呼...真実はいつも一つ!

first: 这是一个逗号表达式,其中包括一个赋值运算(a = a + i)和一个单纯的加法运算(a + j)。可能会问: "为什么不是一个赋值表达式中包含一个逗号表达式,就比如这样: a = (a + i, a + j)?"。有请今日第一位主角: "运算符的优选级" ==》这里有两个链接: "Dajinpang_运算符的优先级(从高到低)" 和 "001_C语言中运算符的优先级"。康完就请继续。

second: 所以啊,这个表达式的值就是逗号表达式的值。而逗号表达式有一个特点,那就是它的值永远只取决于最后一个子式(最右边的式子)的值。也就是说本题中此表达式的值为: a + j,得出答案为105。这时候又有仙女会问了: "这个char和int类型是怎样转换的嘞?"(大概意思就是这样),有请今日第二位主角:"C语言中的数值类型的转换"(跳来跳去不方便,直接开锤) ===》

 

三. C语言中的数值类型的转换 ===》

数据类型转换就是将数据(变量、数值、表达式的结果等)从一种类型转换为另一种类型。分为两种类型: 

1. 自动类型转换: 编译器默默地、隐式地、偷偷地进行的数据类型转换,这种转换不需要程序员干预,会自动发生。所以也称之为: 隐式类型转换。一般情况下,遇到隐式转换无外乎一下两种情况 ===》

--(1). 将一种类型的数据赋值给另外一种类型的变量时就会发生自动类型转换,eg:(我太懒了,不想写头文件,安利python)

float a = 100;      // 将整数类型的值赋值给单精度浮点数类型的变量
printf("%f", a);    // 输出:100.000000(默认是保留后六位)

这种方式很显然地扩大(提高)了数值的精度,有提高就当然会有降低了,比如这样 ↓

float f = 100;
int n = f;              // 将单精度浮点数类型的值赋值给一个整数类型的值
printf("%d", n);      // 输出:100
printf("%f", f);    // 输出:100.000000
// 为什么要写这个printf("%f", f); : 管我,我爱(留下做铺垫的)

之前有提过f的值是单精度浮点数类型的100.000000,但是将它赋值给整数类型的n之后,虽然f是不变的,但是在n上体现出精度降低,导致数据失真。

所以,在赋值运算中,赋值号两边的数据类型不同时,需要把右边表达式的类型转换为左边变量的类型,这可能会导致数据失真,或者精度降低;所以说,自动类型转换并不一定是安全的。对于不安全的类型转换,编译器一般会给出警告(warning)。

--(2). 在不同类型的数据参与运算的时候,编译器也会自动的将数据的类型进行转换,保证参加运算的数据的数据类型统一。数据类型转换的规则有如下3点: 

  1st. 精度最高原则: 转换按数据长度增加(数据精度增加)的方向进行,以保证数值不失真,或者精度不降低。

  2nd. 所有的浮点运算都是以双精度进行的,即使运算中只有 float 类型,也要先转换为 double 类型,才能进行运算。

  3rd. char 和 short 参与运算时,必须先转换成 int 类型。

#include<stdio.h>
int main(){
    int a = 3;
    double b = 1.4;
    // 输出:    a的字节长度为4
    printf("    a的字节长度为%d\n", sizeof(a));
    // 输出:    b的字节长度为8
    printf("    b的字节长度为%d\n", sizeof(b));
    // 输出:a + b的字节长度为8
    printf("a + b的字节长度为%d\n", sizeof(a + b));
    
    // 输出:    a的字节长度为4
    printf("    a的字节长度为%d\n", sizeof(a));
    // 输出:    b的字节长度为8
    printf("    b的字节长度为%d\n", sizeof(b));
    // 为什么还有有一个这?对,这又是一个伏笔 
    return 0;
}
View Code

呐,上面就印证了"精度最高原则"(这是我自己起的名儿),下面俩原则就按照这种方法去弄吧,懂的早就懂了,不懂的再多说也还是不懂(真不懂就继续问【手动龇牙】)。就像很多教科书上有记载 ===》

 

2. 强制类型转换: 自动类型转换是编译器根据代码的上下文环境自行判断的结果,毕竟电脑终究只是一台电脑,有时候并不是那么“智能”,不能满足所有的需求。如果需要,程序员也可以自己在代码中明确地提出要进行类型转换,这称为强制类型转换。通用的格式为:(type_id) expression ===》就是"(类型名) 表达式",emm...英语有进步,微笑在天上飞。

举一个经典的例子叭,我也不想想了(算了,还是自己写了一个,尊重"版权") ===》

#include <stdio.h>
int main(){
    int dividend = 10;    // 被除数 
    int divisor = 7;    // 除数 
    double result_1, result_2;  // 结果 
    
    // 不强制转换
    result_1 = dividend / divisor;
    // result_1 is 1.000000!
    printf("result_1 is %lf!\n", result_1);
    
    // 强制转换 
    result_2 = (double) dividend / divisor;
    // result_2 is 1.428571!
    printf("result_2 is %lf!\n", result_2);

    return 0;
}
View Code

虽然说 result_1 是 double 类型,可以接收小数部分,但是怎料小数部分提前就被编译器给"阉"了,它只能接收到整数部分,显示: 1.000000,这就导致除法运算的结果严重失真。所以这个时候就需要我们这些程序员亲自发下谕旨,跟编译器说: "东西留着,害得用呢",这样 result_2 是 double 类型,可以接受小数不分,而且小数也存在,所以 result_2 就会显示: 1.4.....

 

四. 还有一件事: 类型转换只是临时性的 ===》

无论是自动类型转换还是强制类型转换,都只是为了本次运算而进行的临时性转换,转换的结果也会保存到临时的内存空间,不会改变数据本来的类型或者值。就像前面所说的: printf("%f", f);f并没有改变,再看前面sizeof()的那个,也是如此。

 

五. 写在最后 ===》

在C语言中,有些类型既可以自动转换,也可以强制转换,例如 int 到 double,float 到 int 等;而有些类型只能强制转换,不能自动转换,例如以后将要学到的 void * 到 int *,int 到 char * ...等,如果此时不明确指出类型的转换,编译器将会无法正常编译。

可以自动进行的类型转换一般风险较低,不会对程序带来严重的后果,例如,int 到 double 没有什么缺点,float 到 int 顶多是数值失真。只能强制进行的类型转换一般风险较高,或者行为匪夷所思,例如,char * 到 int * 就是很奇怪的一种转换,这会导致取得的值也很奇怪,再如,int 到 char * 就是风险极高的一种转换,一般会导致程序崩溃。

使用强制类型转换时,程序员自己要意识到潜在的风险。

转载: C语言数据类型转换(自动类型转换+强制类型转换)

posted @ 2020-02-26 20:50  BNTU  阅读(286)  评论(0编辑  收藏  举报