[位操作]数据位提升的隐式转换

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

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。

时间: 2024-10-28 16:02:35

[位操作]数据位提升的隐式转换的相关文章

大数据学习:Scala隐式转换和并发编程(DT大数据梦工厂)

很多Spark代码中使用了隐式转换.隐式参数.隐式类.隐式对象 如果不掌握,基本在读写复杂代码的时候读不懂 并发编程,怎么样进行高效并发,相互之间怎么通信,Spark这种分布式并发肯定非常重要 (Actor.Akka) ==========隐式转换函数============ 可以手动指定将某种类型的对象转换成其它类型的对象或者类 转换原因:假设制定好接口 比如File,我们想要File.dtSpark的方法,在JAVA中不行 如果在Scala里面我们可以进行升级,将File编程其它类型,就用之

【类型转换】 隐式转换 自动提升 强制转换

基本数据类型的类型转换 Java中基本数据类型共有8种,分别是:布尔型boolean,字符型char和数值型byte/short/int/long/float/double.由于字符型char所表示的单个字符与Ascii码中相应整形对应,因此,有时也将其划分到数值型中. 基本数据类型中,布尔类型boolean占有一个字节,由于其本身所代表的特殊含义,boolean类型与其他基本类型不能进行类型的转换(既不能进行自动类型的提升,也不能强制类型转换), 否则,将编译出错. 数值类型在内存中直接存储其

SQL Server中提前找到隐式转换提升性能的办法

    http://www.cnblogs.com/shanksgao/p/4254942.html 高兄这篇文章很好的谈论了由于数据隐式转换造成执行计划不准确,从而造成了死锁.那如果在事情出现之前发现了这类潜在的风险岂不是更好?     那么我们来看一个简单的例子,如代码清单1所示.   1: SELECT * 2: FROM HumanResources.Employee 3: WHERE NationalIDNumber = 243322160 4:  5: SELECT * 6: FR

0097 数据类型转换 之 转为字符串:toString()、String() 、隐式转换

什么是数据类型转换? ? 使用表单.prompt 获取过来的数据默认是字符串类型的,此时就不能直接简单的进行加法运算,而需要转换变量的数据类型.通俗来说,就是把一种数据类型的变量转换成另一种数据类型,通常会实现3种方式的转换: 转换为字符串类型 转换为数字型 转换为布尔型 8.4.1.转换为字符串 toString() 和 String() 使用方式不一样. 三种转换方式,更多第三种加号拼接字符串转换方式, 这一种方式也称之为隐式转换. // 1. 把数字型转换为字符串型 变量.toString

Java基础——隐式转换vs强制转换

在定义变量时,有许多要注意的问题,一不小心就会出现损失精度或者不兼容类型等问题. 例如: 1.定义长整型数据时,必须加后缀l或L long l =123456789012345L 2.定义单精度类型时(7-8位有效数字),必须加后缀 f 或 F float f = 12.5F 3. boolean类型不可以转换为其它的数据类型. 这其中,我们常常会遇到数据类型的转换问题,最为常见的要属隐式转换和强制转换了,我们来分析一下. 隐式转换 特征: 从小到大,可以隐式转换,数据类型将自动提升. byte

MySQL性能优化:MySQL中的隐式转换造成的索引失效

数据库优化是一个任重而道远的任务,想要做优化必须深入理解数据库的各种特性.在开发过程中我们经常会遇到一些原因很简单但造成的后果却很严重的疑难杂症,这类问题往往还不容易定位,排查费时费力最后发现是一个很小的疏忽造成的,又或者是因为不了解某个技术特性产生的. 于数据库层面,最常见的恐怕就是索引失效了,且一开始因为数据量小还不易被发现.但随着业务的拓展数据量的提升,性能问题慢慢的就体现出来了,处理不及时还很容易造成雪球效应,最终导致数据库卡死甚至瘫痪.造成索引失效的原因可能有很多种,相关技术博客已经有

oracle数据类型及其隐式转换

oracle有三种最基本的数据类型,即字符型.数值型.日期型. oracle提供的单行函数中,针对不同的数据类型,提供大量实用的函数,同时提供一系列数据类型转换函数,如下: 1)to_char     数值.日期->字符型     语法:to_char(num|date,[format mask],[nls_parameters])     参数:num|date 待转换的数值或者日期             format mask:可选参数 数字->字符型的可用格式 格式元素 元素说明 格式

隐式转换——内置数据类型

概述 隐式转换是指在初始化或赋值或函数调用时编译器隐式完成的不同类型之间的转换 常量转内置类型 对于没有任何常量后缀的整型或者浮点型在进行初始化或赋值或作为函数实参传递时需要进行常量类型匹配 整型 int->long int顺序匹配 浮点型 默认都是double类型 用常量初始化或者赋值给内置类型变量时,编译器会判断常量的值是否在内置类型变量取值范围内,如果在内置类型变量取值范围内,编译器会正确初始化或者赋值,否则,编译器会给出警告提示 内置类型之间转换 布尔型转算术类型(整型和浮点型) tru

编写高质量代码——提防隐式转换带来的麻烦

在C/C++ 语言,允许在不同类型的数据之间进行某一操作或混合操作,如果类型不同,则要将数据转换成相同的数据类型(隐式转换和显示转换). ========================= 隐式转换主要发生的情形: ▉基本类型之间的隐式转换 C/C++ 中规定的两个通用转换原则: 1)为防止精度损失,类型总是被提升为较宽的类型. 2)所有含有小于整数类型的算术表达式在计算之前其类型都被转换成整形. 对于C++最直接的害处是:可能导致 重载函数 产生二义性. 例如: void Print(int