C语言各种类型之间转换详解
目录
- 1. C基本类型变量
- 2. 符号扩展
- 2.1 规则一:
- 2.2 规则二:
- 2.3 规则三:
- 3. 零扩展
- 4. 长类型转换为短类型
- 5. 自动类型转换
- 5.1 赋值时的类型转换
- 5.2 运算时的类型转换
- 6. 有符号和无符号数的比较
- 6. 无符号数回绕
- 参考资料:
1. C基本类型变量
char/short/int/long/long long 以及其对应的无符号类型,short/double等。
基本类型 | 输出格式符 |
---|---|
char | %c, %d, %u |
short | %hd |
int | %d |
long | %ld |
long long | %lld |
unsigned char | %c, %d, %u |
unsigned short | %hu, %ho, %hx |
unsigned int | %u, %o, %x |
unsigned long | %lu, %lo, %lx |
unsigned long long | %llu, %llo, %llx |
float | %f |
double | %lf |
在类型转换中,根据待转换的类型划分,可分为对有符号类型的转换和无符号类型的转换,对应的转换规则为符号扩展和零扩展。
2. 符号扩展
即,对于要扩展的量为有符号数,扩展存储位数的方法。
2.1 规则一:
在新的高位字节使用当前当前最高有效位即符号位的值进行填充。
例1:
char a = 0xff; // 有符号值为 -1,二进制为 1111 1111,其中最高位为符号位
short b = a; // b的有符号值为 -1,在内存中存储的值为 1111 1111 1111 1111
例2:
char a = 1; // 有符号值为 1,二进制位 0000 0001,其中最高位为符号位
short b = a; // 有符号值为 1,在内存中存储的值为 0000 0000 0000 0001
2.2 规则二:
对于同一长度的数据类型中有符号与无符号数的相互转化,直接将内存中的数据赋给要转化的类型,数值大小会发生变化。
例3:
char a = 0xff; // 有符号值为 -1,二进制为 1111 1111,其中最高位为符号位
unsigned char b = a; // 无符号值为 255,在内存中存储的值仍为 1111 1111,最高位为数据位
2.3 规则三:
对于短类型扩展为长类型时,若短类型与长类型分属于有符号数与无符号数,则先按规则一进行类型的扩展,再按规则二直接将内存中的数值原封不动的赋给对方(若短类型与长类型分属于无符号数与有符号数,则先按下一节中零扩展规则进行扩展,再执行规则二)。
例4:
char a = 0xff; // 有符号值为 -1,二进制为 1111 1111,其中最高位为符号位
unsigned short b = a; // 按规则一,扩展为 short 类型: 1111 1111 1111 1111,有符号值为 -1// 再按规则二,扩展为 unsigned short 类型:1111 1111 1111 1111,无符号值为 2^16 - 1
3. 零扩展
即,对于要扩展的量为无符号数,扩展存储位数的方法。
在新的高位直接填 0。若扩展类型从无符号短类型到有符号长类型,则首先由无符号短类型扩展为无符号长类型,再由无符号长类型转化为有符号长类型。
例1:
unsigned char a = 0xff; // 无符号值为 255,二进制为 1111 1111
unsigned short b = a; // b 经过零扩展后,无符号值为 255,内存中存储的值为 0000 0000 1111 1111
例2:
unsigned short i = 65535;
printf("%d\n", i); // 65535,零扩展:0xffff(ushort) -> 0x0000ffff(uint) -> 0x0000ffff(int)signed short i = 65535;
printf("%d\n", i); // -1,符号扩展:0xffff(short) -> 0xffffffff(int)
4. 长类型转换为短类型
对于长数据类型缩减为短数据类型的情况,会直接截取低字节赋给短数据类型。
例2:
unsigned short a = 0x55ff; // 无符号值,二进制为 0101 0101 1111 1111
char b = a; // 有符号值为 -1,二进制为 1111 1111
5. 自动类型转换
自动类型转换就是编译器默默地、隐式地、偷偷地进行的数据类型转换,这种转换不需要程序员干预,会自动发生。
5.1 赋值时的类型转换
将一种类型的数据赋值给另外一种类型的变量时就会发生自动类型转换,例如:
float f = 100;
100 是 int 类型的数据,需要先转换为 float 类型才能赋值给变量 f。再如:
int n = f;
f 是 float 类型的数据,需要先转换为 int 类型才能赋值给变量 n。
在赋值运算中,赋值号两边的数据类型不同时,需要把右边表达式的类型转换为左边变量的类型,这可能会导致数据失真,或者精度降低;所以说,自动类型转换并不一定是安全的。对于不安全的类型转换,编译器一般会给出警告。
5.2 运算时的类型转换
在不同类型的混合运算中,编译器也会自动地转换数据类型,将参与运算的所有数据先转换为同一种类型,然后再进行计算。转换的规则如下:
- 转换按数据长度增加的方向进行,以保证数值不失真,或者精度不降低。例如,int 和 long 参与运算时,先把 int 类型的数据转成 long 类型后再进行运算;
- 所有的浮点运算都是以双精度进行的,即使运算中只有 float 类型,也要先转换为 double 类型,才能进行运算;
- char 和 short 参与运算时,必须先转换成 int 类型。
不同类型运算时,类型转换原则如下图:
6. 有符号和无符号数的比较
有符号数与无符号数运算时数强制类型转换方式:
当执行一个运算时(如下面的a>b),如果它的一个运算数是有符号的而另一个数是无符号的,那么C语言会隐式地将有符号参数强制类型为无符号数,并假设这两个数都是非负的,来执行这个运算。
#include <stdio.h> int main()
{ int a = -1; unsigned int b = 1; if(a > b) printf("a > b, a = %d, b = %u\n", a, b); else printf("a <= b, a = %d, b = %u\n", a, b); return 0;
}
6. 无符号数回绕
下面代码中,若输入 length = 0,则 length - 1的运算会发生回绕(unsigned int 0 - 1 = 2^32 - 1),导致数组越界访问。
int sum_elements(int a[], unsigned int length)
{ int i = 0; int sum = 0; for(i = 0; i <= length - 1; ++i) sum += a[i]; return sum;
}
将上述代码中 for 循环改为下述形式,可以避免这个问题:
for(i = 0; i < length; ++i)
参考资料:
1-4:https://blog.csdn.net/zhangzhi123456789/article/details/49589137
C语言类型转换:http://c.biancheng.net/view/1775.html
6:https://blog.csdn.net/u010765526/article/details/73613815
有符号数存储方式:https://blog.csdn.net/zy986718042/article/details/71699079
C语言各种类型之间转换详解相关推荐
- python datetime to timestamp_python timestamp和datetime之间转换详解
做开发中难免时间类型之间的转换, 最近就发现前端js和后端django经常要用到这个转换, 其中jsDate.now()精确到毫秒,而Python中Datetime.datetime.now()是精确 ...
- python中时间戳、字符串之间转换详解
[转载]python中时间戳.字符串之间转换详解 (2013-04-30 17:36:07) 转载▼ 标签: 转载 原文地址:python中时间戳.字符串之间转换详解作者:doris0920 1)秒数 ...
- 十进制与二进制之间转换详解
文章目录 十进制与二进制之间转换详解 (一)十进制数转二进制数 1.1 十进制正整数转二进制 1.2 十进制负整数转二进制 1.3 十进制小数转二进制数 (二) 二进制数转成十进制数 2.1 二进制整 ...
- python timestamp转date_python timestamp和datetime之间转换详解
做开发中难免时间类型之间的转换, 最近就发现前端js和后端django经常要用到这个转换, 其中jsDate.now()精确到毫秒,而Python中Datetime.datetime.now()是精确 ...
- C语言volatile类型限定符详解
一.volatile类型限定符 volatile是一个类型修饰符(type specifier),就像我们熟悉的const一样,它是被设计用来修饰被不同线程访问和修改的变量:volatile的作用是作 ...
- 二进制转换八进制图解_二进制、八进制和十六进制之间转换详解
我们平时使用的数字都是由 0~9 共十个数字组成的,例如 1.9.10.297.952 等,一个数字最多能表示九,如果要表示十.十一.二十九.一百等,就需要多个数字组合起来. 例如表示 5+8 的结果 ...
- C语言数组之间赋值详解
数组之间的赋值,C语言数组之间赋值详解 (biancheng.net)
- UNICODE与UTF-8的转换详解
UNICODE与UTF-8的转换详解 1 编码 在计算机中,各种信息都是以二进制编码的形式存在的,也就是说,不管是文字.图形.声音.动画,还是电影等各种信息,在计算机中都是以0和1组成的二进制代码表示 ...
- UNICODE与 UTF8的转换详解
转载请注明出处: http://www.ins1000.cn/KnowledgeActionForReader?action=read&id=104 源文件下载地址:UTF- 8的转换详解(W ...
最新文章
- Error: Cannot find module ‘webpack-cli/bin/config-yargs‘
- 工作中Oracle常用的SQL
- Coreseek:部门查询和增量索引代替实时索引
- 【赠书】图表示学习+图神经网络:破解AI黑盒,揭示万物奥秘的钥匙!
- SQL SERVER 2012启动失败 because upgrade step 'SSIS_hotfix_install.sql' 失败
- [转] 移动前端不得不了解的HTML5 head 头标签
- python 3.x 爬虫基础---http headers详解
- 基于TextRank算法的文本摘要(附Python代码)
- (转)淘淘商城系列——首页轮播图展示
- [Git] 删除远程仓库的文件
- Office 2007,在编辑Word时,文件经常无法保存会丢失
- AlphaGo Zero代码迟迟不开源,TF等不及自己推了一个
- Repast HPC 2.0安装及实例模型运行总结
- 机器学习导论(五)-神经元网络
- 《3D游戏与计算机图形学中的数学方法》读书笔记--四元数
- 最新MTK芯片型号汇总,MTK开发资料大全下载
- 科普向-----验证码
- 产品分析————拼多多
- AutoESL与Xilinx那些人和事
- 阿里云体验--搭建超级小班课网课系统