C语言强制类型转换规则实例详解

目录
  • 整形之间的强制转换
    • 无符号转有符号
    • 有符号转无符号
    • 不同长度数字转化中的截断
  • 整形与浮点数的强制类型转换
  • 总结

整形之间的强制转换

在强制类型转换中,我们常用的整形强制转换有无符号和有符号类型的强制转换。所以首先我们得介绍一下计算机中存储数字的方式,计算机中通常以补码的形式来存储数据,以8位数据为例,二进制与有符号数的对应关系为:

0 1 2 127 -128 -127 -1
0000 0000 0000 0001 0000 0010 0111 1111 1000 0000 1000 0001 1111 1111

无符号转有符号

0 1 2 127 128 129 255
0000 0000 0000 0001 0000 0010 0111 1111 1000 0000 1000 0001 1111 1111

所以对于有符号数,首先最高位是正负的标志位。要将无符号数强制转化为有符号数时,其内存上的二进制是不会改变的,只是我们对它的解释变了,即无符号数128强制转化有符号数即-128。

当然这样引申出来的一种好处就是对于有符号数的判断,如

char a;
...
if((a>=0)&&(a<80))
{
....
}

可以使用强制转化,省去一个判断条件

char a;
...
if( ((unsigned char)a) < 80)
{
....
}

有符号转无符号

将有符号数变成无符号数时,情况也类似,如8位的有符号数120转无符号也是120,但8位的-1转无符号则为255。所以当我们在有符号数的计算中,想保留大于等于0的数,不能通过强制转化来完成,必须得加判断:

char a,b,d;
unsigned char c;
....
c=(unsigned char)(a+b);  (×):当运算结果小于0时c会异常,变成超级大数

d=a+b;
c = (d<0)?0:d;           (√)

不同长度数字转化中的截断

比如我有一个8位的有符号数-1,要转换为一个16位的有符号数,那么结果仍旧是-1。首先我们要明确一点,那就是虽然8位的有符号数-1的二进制原本1111 1111,但载入32位的cpu中运算时,它将转化为32位的有符号数进行运算,即int类型的-1。所以对于char类型的数据,即使运算结果超过了该类型,其实也不会发生异常:

char a=127,b=127,c=127,e;
int d;
....
e=a+b+c;   	 (×):当运算结果超过存储类型的表示范围时,会因截断产生错误
d=a+b+c;     (√):32位的int类型足够存储结果。

所以我们如果把不同长度的数字进行类型转换,只有两个步骤:

1、将该数表示为32位
2、将32位数截断为结果类型

不过,可以确定的一点就是,进行第一步时,数的值不会发生变化:

比如8位有符号数-1(1111 1111)将转化为32位的-1(1111 1111 1111 1111 … 1111 111)。
而8位的无符号数255(1111 1111)转为32位时,也仍旧是255:(0000 0000…0000 0000 1111 111)。

但进行第二步转换时,值会由于截断而发生变化,而这个截断一般是高位截断(舍弃高位,保留低位):

如int类型的255(0000 0000 … 0000 0000 1111 1111)转化为8为的unsigned char类型时,前面的0将被截断,只保留低8位,即255(1111 1111),当然,若是转为8为的有符号char类型,则为-1(1111 1111)。截断是二进制层面的位数截断,与实际值无关。

整形与浮点数的强制类型转换

我们都知道浮点数float类型一般遵循ieee754标准,有符号位,阶码和尾数:

与整形相同,符号位是1时代表负数,是0则为正数。而阶码代表小数点在哪儿,类似于科学计数法100会被表示为 1.0 × 10^2。详细的这里不介绍了,我们重点放在强制转化上:

对于一个int类型的数,只要在浮点数的表示范围内,便可以正确的转为浮点数格式。

但是对于一个浮点类型的数,在转化为整形时,则会只保留整数位,如:

int a= (int)0.1;    即a=0
int a= (int)1.1;    即a=1
int a= (int)1.5;    即a=1
int a= (int)-1.5;   即a=-1

所以如果要四舍五入之类的的,则不能靠强制转换,得用相关的函数。当然若是转为其他整形,则结果将有32位的整形结果进行截断得到。

当然,强制转换和 floor 这个函数的功能其实很像,floor函数的功能是向下取整:

int a= floorf(0.1);    即a=0
int a= floorf(1.1);    即a=1
int a= floorf(1.5);    即a=1

对于大于0的浮点数,他俩其实可以替换,而当小于0时,他俩区别很大:

int a= floorf(-0.1);    即a=-1
int a= floorf(-1.1);    即a=-2

int a=(int)-0.1;        即a=0
int a=(int)-1.1;        即a=-1

强制转化的结果,会产生正负0这种概念,如-0.9到0.9强制转化结果都为0。使用强制转化时会产生越界输出

总结

到此这篇关于C语言强制类型转换规则的文章就介绍到这了,更多相关C语言强制类型转换内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言中自动隐式转换与类型强制转换实例分析

    本文通过一个C程序实例对C语言中自动隐式转换与类型强制转换的注意点进行深入分析,详情如下: 先看一个C程序: #include<stdlib.h> #include<stdio.h> #include<conio.h> double proc(int q){ int n; double sum,t;//本例的关键就在这几个变量的类型上 sum = 2.0; while(sum<=q){ t=sum; //sum = sum+(n+1)/n;//自动隐式转换 sum

  • C语言基础隐式类型转换与强制类型转换示例解析

    目录 类型转换 隐式类型转换 强制类型转换 类型转换 数据有不同的类型,不同类型数据之间进行混合运算时必然涉及到类型的转换问题. 转换包括隐式类型转换和强制类型转换. 类型转换的原则:占用内存字节数少(值域小)的类型,向占用内存字节数多(值域大)的类型转换,以保证精度不降低. 隐式类型转换 隐式转换也称为自动转换,遵循一定的规则,由编译器自动完成. C的整型算数运算总是至少以缺省整型类型的精度来进行,为了获得这个精度,表达式中的字符和短整形操作数在使用之前都被转换成普通整型,这种转换为整型提升.

  • C语言强制类型转换规则实例详解

    目录 整形之间的强制转换 无符号转有符号 有符号转无符号 不同长度数字转化中的截断 整形与浮点数的强制类型转换 总结 整形之间的强制转换 在强制类型转换中,我们常用的整形强制转换有无符号和有符号类型的强制转换.所以首先我们得介绍一下计算机中存储数字的方式,计算机中通常以补码的形式来存储数据,以8位数据为例,二进制与有符号数的对应关系为: 0 1 2 … 127 -128 -127 … -1 0000 0000 0000 0001 0000 0010 … 0111 1111 1000 0000 1

  • Spring MVC自定义日期类型转换器实例详解

    Spring MVC自定义日期类型转换器实例详解 WEB层采用Spring MVC框架,将查询到的数据传递给APP端或客户端,这没啥,但是坑的是实体类中有日期类型的属性,但是你必须提前格式化好之后返回给它们.说真的,以前真没这样做过,之前都是一口气查询到数据,然后在jsp页面上格式化,最后展示给用户.但是这次不同,这次我纯属操作数据,没有页面.直接从数据库拿数据给它们返数据.它们给我传数据我持久化数据,说到这里一个小问题就默默的来了. 首先把问题还原一下吧(这是一个数据导出功能),下图中用红框圈

  • C/C++语言宏定义使用实例详解

     C/C++语言宏定义使用实例详解 1. #ifndef 防止头文件重定义 在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成 一个可执行文件时,就会出现大量"重定义"的错误.在头文件中实用#ifndef #define #endif能避免头文件的重定义. 方法:例如要编写头文件test.h 在头文件开头写上两行: #ifndef TEST_H #define TEST_H //一般是文件名的大写 头文件结尾写上一行: #endif 这样一个工程文件里同时

  • Kotlin语言编程Regex正则表达式实例详解

    目录 前言 Regex 构造函数 常用正则表达方法 示例展示 1.containsMatchIn(input: CharSequence) 包含指定字符串 2.matches(input: CharSequence) 匹配字符串 3.find(input: CharSequence, startIndex: Int = 0) 查找字符串,并返回第一次出现 4.findAll(input: CharSequence, startIndex: Int = 0) 查找字符串,返回所有出现的次数 5.r

  • GO语言数组和切片实例详解

    本文实例讲述了GO语言数组和切片的用法.分享给大家供大家参考.具体分析如下: 一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. (1)数组的创建. 数组有3种创建方式:[length]Type .[N]Type{value1, value2, ... , valueN}.[...]Type{value1, value2, ... , valueN} 如下: 复制代码 代码如下: func test5() {     var iarray1 [5]int32    

  • ES6中Symbol类型用法实例详解

    本文实例讲述了ES6中的Symbol类型.分享给大家供大家参考,具体如下: Symbol是在ES6中新加入的类型. 正如我们所知,JavaScript中有以下几种类型: Undefined ,Null ,Boolean ,Number ,String, Object. 但是上述类型在处理某些情况的时候是远远不够的.下面我们来举一个例子: 假设我们要移动div,也需要在某些情况下判断该div是否处于移动状态,所以我们会想到给div这类的对象设置一个属性. if (element.isMoving)

  • Java泛型之类型擦除实例详解

    目录 前言 泛型是什么? 泛型的定义和使用 泛型类 泛型方法 泛型类与泛型方法的共存现象 泛型接口 通配符 ? 无限定通配符 <?> <? extends T> 类型擦除 类型擦除带来的局限性 泛型中值得注意的地方 Java 不能创建具体类型的泛型数组 泛型,并不神奇 总结 前言 泛型,一个孤独的守门者. 大家可能会有疑问,我为什么叫做泛型是一个守门者.这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇.泛型是 Java 中一个很小巧的概念,但同时

  • Swift中风味各异的类型擦除实例详解

    目录 前言 什么时候需要类型擦除? 通用包装器类型擦除 闭包类型擦除 结语 前言 Swift的总体目标是既强大到可以用于底层系统编程,又足够容易让初学者学习,这有时会导致相当有趣的情况——当Swift的类型系统的力量要求我们部署相当高级的技术来解决乍一看可能更微不足道的问题. 大多数Swift开发人员会在某一时刻或另一时刻(通常是马上,而不是日后)会遇到这样一种情况,即需要某种形式的类型擦除才能引用通用协议.从本周开始,让我们看一下是什么使类型擦除在Swift中成为必不可少的技术,然后继续探索实

  • Go语言kylin任务自动化实例详解

    目录 前言 任务 自动化实现 初始化 cube提交build cube运行结果检查 重构cube 历史job清理 时间戳 小结 前言 kylin是一个开源的OLAP分析引擎,具有亚秒级查询大表的能力 通过kylin提供的cube预构建功能,省去了不断写sql查询hive的麻烦,强化了任务统一管理和结果快速呈现的效果 kylin官网: https://kylin.apache.org/cn/ 任务 当kylin集群比较大,和有多个kylin集群时,说明cube也越来越多,几百上千个cube便是常用

  • linux C语言开发管道通信实例详解

    linux C语言开发管道通信 Linux系统本身为进程间通信提供了很多的方式,比如说管道.共享内存.socket通信等.管道的使用十分简单,在创建了匿名管道之后,我们只需要从一个管道发送数据,再从另外一个管道接受数据即可. #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> int pipe_default[2]; int main() { pid_t

随机推荐