• C语言细节——献给入门者(三)


    C语言细节——献给入门者(三)

    >>主题:关于强制类型转换

      先来瞎扯下强制类型转换,c语言有很多数据类型,long,short,int,float,double,bool,char等等。当我们要将一种数据类型赋值给另一种数据类型,或者将某个操作数进行如此的转化的时候,就用到了强制类型转换。 

      强制类型转换分成两种:1.显示强制类型转换(主动)  2.隐式强制类型转换(被动/自动)

      要区分这两者很简单,看下面例子:(we assume that b is a variable of integer.)

    char a = (char)b;
    
    char a = b;

     所以区分两者只要看这个(char)是否显式的写出来。但我们要注意,这两个的区别绝对不是这么简单。让我们看下去...

    》》》如果一个运算符两边的运算数类型不同,先要将其转换为相同的类型,即较低类型转换为较高类型,然后再参加运算,转换规则如下图所示。

    这段和这图是我百度来的,他说计算机会主动把float,int分别转换成double,long计算,后来想来一下发现跟计算机组成学的不一样,况且如果都这样计算,那还需要小数据类型干嘛呢?计算机速度何必非得用双精度来测量?后来我自己测了一下,发现果然是瞎扯,我就不用这个图说啦~(附上测试代码)

      (ps:以下按照int为32位来说明):      

          

    测试代码:

    #include <stdio.h>
    int main()
    {
        int a=1,b=2;
        int c=a+b;
        long aa=2,cc=4;
        long bb=aa+cc;
    
        printf("%d
    ",c );
        printf("%ld
    ",bb );
        return 0;
    }

    反汇编后所得(部分代码):

     1     movl    $0, -4(%rbp)
     2     movl    $1, -8(%rbp)
     3     movl    $2, -12(%rbp)
     4     movl    -8(%rbp), %eax
     5     addl    -12(%rbp), %eax
     6     movl    %eax, -16(%rbp)
     7     movq    $2, -24(%rbp)
     8     movq    $4, -32(%rbp)
     9     movq    -24(%rbp), %rcx
    10     addq    -32(%rbp), %rcx
    11     movq    %rcx, -40(%rbp)
    12     movl    -16(%rbp), %esi
    13     movb    $0, %al

    感觉一下子打乱我思路了,让我捋一捋。。。

    》》》先看下两个优先级的例子,很多人可能没有注意到:

    num = (double)k/m;

    在这里,无论double是强制类型转换了k还是k/m,答案都一样;但这边的double是修饰k的,因为括号的优先级是高于/的;

    如果想要double修饰k/m的话就可以这样做:

    num = (double)(k/m);

    另一个例子:

    a  =  (int)father->age;

    这里很明显int是修饰age的,因为father是不能强制类型转换成int类型的;这里是因为->的优先级高于括号;

    》》》接下来看看有关数据类型的几种例子

    case 1:

    int a,b=2;
    a=(int)b; 

    这里 因为a,b都是int型,所以这边的(int)可以不用,即显式隐式都是可以的;

    case 2:

    int a;
    char b='A';
    a=(int)b; 
    char a;
    int b=65;
    a=(char)b;

    首先这个例子能互换是因为字符和整型之间可以通过ascii码转换,其次char占一个字节而int占4个字节;

    在前一个大数给小数的情况下,显式隐式编译器都通过,但是很有可能导致溢出,所以需要自己注意;

    后一个系统自动会把b扩成4字节赋值给a(b还是1字节)

    case 3:

    int b=-1;
    unsigned int a;
    a=b;
    printf("%d
    ",a);

    这里unsigned int的范围是0~65535 ,其实当a=b后,a的值是65535,但输出却是-1;我一开始没有想通,加了显式转换之后试了一下还是-1,后来才知道%d输出是有符号的int类型,所以输出结果还是-1;

    说到这个我想到之前一个学弟问我%e的问题;

    那是书上的一个例子,输入用%e,输出却用%f,他一直奇怪为什么输出是71.820000而不是7.182000e+01;

    你不用%e输出,怎么会看到7.182000e+01呢?就算你用%f输入%e输出也能看到这样的形式啊。

    我觉得学语言不能光学个语法,重点需要了解数据是如何存在于计算机内部的。

    你需要知道无论怎么样输入输出,同样的数据存在计算机里面是不变的,只是我们在屏幕上看到的显示方式不一样而已,就像一个月饼,有包装和无包装它就是个月饼,里面的馅还是那个馅。

    扯的有点远了。今天先写到这里发出来吧。下次再补充,EDG炸了我看的很难受= =。

    ========================================================================================

    2015/11/16 补充:

    本次补充主要根据《The C Programming Language》

     

     1 #include <stdio.h>
     2 
     3 int main()
     4 {
     5     short x = 65535+65535;//-2
     6 
     7     short x1 = 65535;    //取余 但是可以为负数
     8 
     9     short x2 = 65537;    //取余后的最小非负整数
    10     unsigned short y = 65537;    //取余后的最小非负整数
    11 
    12     printf("x1=%d   x2=%d
    " , x1 , x2);
    13     printf("y = %d
    ", y );
    14     return 0;
    15 
    16 }

    ps

    当表达式中包含 u n s i g n e d 类 型 的 运 算 分 量 时 , 转 换 规 则 要 复 杂 一 些 。 主 要 问 题 是 , 在 有 符 号 值与无符号值之间的比较运算取决于机器,因为它们取决于各个整数类型的大小。例如,假定
    i n t 对象占 1 6 位, l o n g 对象占 3 2 位,那么,- 1 L < 1 U ,这是因为 i n t 类型的- 1 U 被提升为 s i g n e d l o n g 类型;但- 1 L > 1 U L , 这 是 因 为 - 1 L 被提升为 u n s i g n e d l o n g 类 型 , 因 此 它 是 一 个 比 较 大 的 正 数 。

    在进行赋值时也要进行类型转换, = 右边的值要转换成左边变量的类型,后者即赋值表达式 结果的类型。

    如前所述,不管是否要进行符号扩展,字符值都要转换成整数值。

    当把较长的整型数转换成较短的整型数或字符时,要把超出的高位部分丢掉。 

  • 相关阅读:
    109. 有序链表转换二叉搜索树
    108. 将有序数组转换为二叉搜索树
    235. 二叉搜索树的最近公共祖先
    538. 把二叉搜索树转换为累加树
    230. 二叉搜索树中第K小的元素
    669. 修剪二叉搜索树
    513. 找树左下角的值
    637. 二叉树的层平均值
    671. 二叉树中第二小的节点
    DDL-Oracle中的5种约束总结(未完待续)
  • 原文地址:https://www.cnblogs.com/sylvialucy/p/4865532.html
Copyright © 2020-2023  润新知