zoukankan      html  css  js  c++  java
  • [位操作]数据位提升的隐式转换

    有关数据位的提升的隐式转换从下面的这三道道笔试题开始:

    signed char a = 0xe0;
    unsigned int b = a;
    unsigned char c = a;
    
    signed char a = 0xe0;
    if(a == 0xe0)
    {
    	printf("haha");
    }
    else
    {
    	printf("nono");
    }
    unsigned int a = 6;
    int b = -20;
    (a + b > 6) ? printf(">6") : printf("<=6");
    
     

    首先明确一点,计算机内存内部位的运算操作都是很简单的小学生运算,硬件的设计是越简单越好,具体这个数是什么,要看你解读这个数的方式。一个很好的例子就是位操作数据溢出的结果这篇博文中的介绍。

    首先来看第一道题目:

    首先任何的常量整数都是int类型的,这是编译器默认的,所以0xe0会被表示为0x00 00 00 e0(32位),赋值给signed char a时,因为char是8位的,所以只取低8位e0赋值过去,这时的赋值仅仅是位数据的拷贝,没有任何的符号等考量在内。所以a得到的数据是e0(1110 0000),这是a把这些二进制当做signed char解释,所以得到的结果是一个负值。

    unsigned int b = a这句话是把a的值负值给一个int,那么要扩展,扩展的方式是跟最高位的位相同,所以b被扩展为0xff ff ff e0,但是b的解读方式是unsigned int,所以会得到一个很大的数字。

    注意:0xe0这个常量整数直接写,编译器把他认为是0x00 00 00 e0,这里不是扩展,不涉及类型的提升,就是默认的位int类型。

    unsigned char c = a把a赋值给一个char类型的变量,这里就是直接的把8位二进制原封不动的拷贝过去,但是c得到这些数据不再按signed char解释,而是按照unsigned char类型解释,所以c是一个很大的整数。

    再来看第二道题目:

    0xe0直接被默认是0x00 00 00 e0,默认为一个正的int类型。赋值给a的时候,截取最后面的8位0xe0赋值给a,但是a拿到这8位数据以后当做signed char来解释。所以是一个负数,所以a是不等于0xe0的。在真正比较的时候a会做位的提升,因为它在和一个int类型的值比较,所以a会提升为0xff ff ff e0,当然不等于0x00 00 00 e0了。

    最后来看第三道题目:

    有符号数和无符号数在一起运算,不要以为遵循的仍然是短的向长的靠齐。以前我们知道,如果一个short和一个int在一起运算,首先编译器会将short自动转换为一个int类型中间变量,然后进行运算。但是有符号数和无符号数在一起运算的话,并不是这样。

    首先说说符号数和无符号数之间的转换。无符号数可以转换为有符号数,有符号数也可以转化为无符号整形,这之间的转换一般编译器也不会给出警告,因为这种转换不涉及到bit丢失的情况,内存内容不会发生任何改变。仅仅是对这块内存的解释不一样而已。

    int a = -3;
    unsigned int b = a; // b= 65533
    //反之一样

    编译器里面有标准的转换,这个是在整形运算的时候出现。
    标准转换的规则是:短的的向长的转;有符号的向无符号的转。如果被转换的数据比转换后的数据要长的话,转换可能会丢失bit数据。通常,编译器会给出警告。
    无符号数据和有符号整数进行运算,是有符号整数向无符号整数靠齐。这里,我们可以总结一条规则:整形数运算,总是遵循一个原则:小的往大的扩展。
    从小到达:short -> unsigned short -> int -> unsigned int。

    所以题目中会首先把b转换成一个很大的是,因为负数的最高位是1,转换成无符号以后,这个1很值钱,所以a+b是一个很大的数,所以最后结果:>6。

    总结一下:

    在数据进行位扩展的时候,首先要确定这个要扩展的数是有符号还是无符号的,然后决定扩展的高位是符号位还是0

    char ch=-1;
    printf(“%02x,%02x”,ch,(unsigned char)ch);
    

      打印的结果是:ffffffff,ff。

    因为%x是十六进制的方式输出整型数据,也就是int,所以两个都要对ch进行高位扩展,但是扩展的方式是不一样的,ch如果是有符号就在高位扩展这个数的符号位,如果ch是无符号的,就直接在高位扩展0。

  • 相关阅读:
    ElasticSearch 常用的查询过滤语句
    ElasticSearch的 Query DSL 和 Filter DSL
    photoshop CS 调整选择区域的大小
    pthread_once重塑singleton模式
    SGU536 Berland Chess
    怎样实现多线程
    [置顶] Linux下将Nutch1.3导入eclipse
    ENC28J60学习笔记——第1部分
    再看copy_on_write缩小临界区的例子
    leetcode Roman Integer
  • 原文地址:https://www.cnblogs.com/stemon/p/4685210.html
Copyright © 2011-2022 走看看