让你学会C语言类型转换"/>
5分钟让你学会C语言类型转换
1、类型转换
在执行算数运算时,计算机只能完成相同类型之间的算数运算,如果两个不同的类型的数据进行算数运算就需要转换为相同类型的数据,进行算数运算。比如short类型的数据和int类型的数据进行算数运算时,需要先将short类型转换为int类型在进行算数运算。
类型转换分为:隐式类型转换和显式类型转换(强制类型转换/强转)。
类型转换需要注意:
1> 小类型向大类型转换时,一般是安全没有问题的。
2> 大类型向小类型转换时,一般出现数据的截断和丢失,不安全,慎用。
3> 类型转换完成之后,并不会改变变量本身的类型,而变量本身的类型有定义变量时的类型决定
4> 在实际开发过程中,涉及到类型转换时,决定权要由程序员决定,不要交给编译器决定。
1.1隐式类型转换
由编译器完成类型的转换,无需程序员的介入,这类转换称为隐式类型转换。
发生隐式类型转换的情况:
1> 在算数表达式或者逻辑表达式中,操作数类型不同时会发生类型转换
2> 在赋值过程中右侧的表达式的类型和左侧变量的类型不匹配时,也会发生类型转换,转换为左侧变量类型之后进行赋值。
3> 函数调用时,实参的类型和形参的类型不一致时也会发生类型转换
4> return返回的表达式的类型和函数的返回类型不一致时,也会发生类型转换。
C99标准的隐式类型转换:
如果表达式中有浮点类型的数据,转换为浮点类型数据进行运算。
浮点类型的优先级从低到高如下:
float --> double --> long double
举例:
int a; float b;
a+b; // 将a隐式转换为float类型之后,在进行算数运算。
float c; double d;
c + d; // 将c隐式转换为double类型之后,在进行算数运算。
如果表达式中都不是浮点类型的,按照以下标准进行提升:
整数类型的优先级从低到高如下:
1> char / unsigned char
2> short / unsigned short
3> int / unsigned int
4> long / unsigned long
5> long long / unsigned long long
四种类型转换发生的具体情况
第1种情况:如果两个操作数都为有符号数或者无符号数,将等级较低的操作数类型,转换为等级较高的操作数类型。
举例:
unsigned int a; unsigned long int b;
a + b; // 变量a被隐式类型转换为unsigned long int类型
第2种情况:如果无符号操作数类型的优先级高于有符号数的类型优先级,将有符号操作数的类型转换为无符号数的操作类型。
举例:
unsigned long int a; int b;
a + b; // 将b变量隐式类型转换为unsigned long int类型。
第3种情况:如果有符号数有效范围可以包含无符号数所有的值,则将无符号数类型隐式转换为有符号数的类型
unsigned int a; long int b; // 64位系统,unsigned int 占4个字节,long int 占8个字节
a + b; // 变量a被隐式类型转换为long int类型。
第4种情况 : 如果以上三种情况都不满足,将两个操作数都转换为与有符号操作数类型相对应的无符号类型。
举例:
long long int a; unsigned long int b;//64位系统,long long int 和unsigned long int都占8字节
a + b; // 将a和b都转换为unsigned long long int类型
unsigned int a; long int b; // 32位系统,unsigned int 和long int 都占4字节
a + b; // 变量a和b被隐式类型转换为unsigned long int类型、
部分代码及实现
#include <stdio.h>
int main(int argc, const char *argv[])
{printf("3 + 3.14 = %lf\n", 3 + 3.14);// int类型的3被隐式转换为double类型之后,在进行运算// 1. 在进行算数运算时,类型不一致时,会发生隐式类型转换int a = 5;float b = 5.12;printf("a + b = %f\n", a + b); // a被隐式类型转换为floatint i = -10;unsigned int j = 5;unsigned int k = i + j; // i会被隐式类型转换为unsigned int类型printf("k = %u\n", k); // 输出很大的数printf("k = %d\n", k); // 输出-5 将无符号整型k,隐式类型转换为int类型// 数据在内存中存放的是二进制的补码// -10的源码,补码,反码// 源码:1000 0000 0000 0000 0000 0000 0000 1010// 反码:1111 1111 1111 1111 1111 1111 1111 0101// 补码:1111 1111 1111 1111 1111 1111 1111 0110// 5的源码,反码,补码一样// 补码:0000 0000 0000 0000 0000 0000 0000 0101// 计算机在计算时将i转换为unsigned int 无符号类型// i = 1111 1111 1111 1111 1111 1111 1111 0110// j = 0000 0000 0000 0000 0000 0000 0000 0101// 和= 1111 1111 1111 1111 1111 1111 1111 1011//按有符号数打印://补码:1111 1111 1111 1111 1111 1111 1111 1011//原码:1000 0000 0000 0000 0000 0000 0000 0101 即为-5//按无符号数打印:则原码等于反码等于补码//原反补码:1111 1111 1111 1111 1111 1111 1111 1011 即为 4,294,967,291unsigned int x = 5;char y = -5;printf("x + y = %u\n", x + y); // 输出0printf("x + y = %d\n", x + y); // 输出0// x的源码,反码,补码// 补码:0000 0000 0000 0000 0000 0000 0000 0101 // y的源码,反码,补码// 源码:1000 0101// 反码:1111 1010 // 补码:1111 1011// 将y提升为unsigned int类型,y是一个有符号的字符类型,高位补充符号位// 提升之后的结果:1111 1111 1111 1111 1111 1111 1111 1011// + 0000 0000 0000 0000 0000 0000 0000 0101// = 0000 0000 0000 0000 0000 0000 0000 0000unsigned int p = 10;short q = -5;// 将q提升为unsigned int类型printf("p + a = %u\n", p + q); // 输出为5printf("p + a = %d\n", p + q); // 输出为5// p 源码,反码,补码// 补码:0000 0000 0000 0000 0000 0000 0000 1010 // q 源码,反码, 补码:// 源码:1000 0000 0000 0101// 反码:1111 1111 1111 1010 // 补码:1111 1111 1111 1011 // 将q提升为unsigned int类型,高位补符号位 // 提升之后数据为:1111 1111 1111 1111 1111 1111 1111 1011 // + 0000 0000 0000 0000 0000 0000 0000 1010 // = 0000 0000 0000 0000 0000 0000 0000 0101// 2. 赋值过程也会发生饮食类型转换,将右侧操作数的类型,// 转换为左侧操作数的类型,不需要考虑数据类型的优先级的问题// 只需要考虑左侧操作数的类型unsigned int s;unsigned short ss = 1000;s = ss; // 将ss隐式类型转换为unsigned int类型的// 小的类型赋值给大的类型,安全。unsigned short u = 0xFFFF;unsigned char c;c = u; // 将u隐式类型转换为unsigned char类型// 大的类型赋值给小的类型,数据会被截断和丢失,不安全,慎用。// 3. 首先对两个操作数进行整数提升,如果两个操作数的类型相同,过程结束// 否则依照以下规则进行提升,一旦遇到可以适配的规则将不在考虑其他的规则。//// 第1种情况:如果两个操作数都为有符号数或者无符号数,将等级较低的操作数类型,// 转换为等级较高的操作数类型。// 举例: unsigned int ui = 1000; unsigned long int uli = 2000;printf("ui + uli = %lu\n",ui + uli); // 变量ui被隐式类型转换为unsigned long int类型//第2种情况:如果无符号操作数类型的优先级高于有符号数的类型优先级,// 将有符号操作数的类型转换为无符号数的操作类型。//举例:unsigned long int uli1 = 10000; int i1 = 2000;printf("uli1 + i1 = %lu\n", uli1 + i1); // 将i1变量隐式类型转换为unsigned long int类型。// 第3种情况:如果有符号数有效范围可以包含无符号数所有的值,// 则将无符号数类型隐式转换为有符号数的类型unsigned int ui1 = 30000; long int li = 40000; // 64位系统printf("ui1 + ui = %ld\n", ui1 + li); // 变量uil被隐式类型转换为long int类型。// 第4种情况 : 如果以上三种情况都不满足,// 将两个操作数都转换为与有符号操作数类型相对应的无符号类型。// 举例:long long int lli = 10000; unsigned long int uli2 = 20000;printf("lli + uli2 = %llu\n", lli + uli2); // 将lli和uli都转换为unsigned long long intreturn 0;
}
1.2 显式类型转换
格式:
(类型名)表达式;举例:
unsigned char c;
(int)c;int a, b;
(long int)a + b;
// ()优先级高于+运算符的优先级
// 先将a强转为long int类型,
// b被隐式类型转换为long int类型,然后在进行加法运算。
#include <stdio.h>
int main(int argc, const char *argv[])
{// 1. 如一个浮点类型,提取浮点类型数据的小数部分float f = 3.1415, f_part;f_part = f - (int)f; // f被强转为int类型 (int)f = 3// (int)f 在进行隐式类型转换得到 3.000000printf("f_part = %f\n", f_part);// 2. 两个整型进行除法运算时,结果可能为小数int a = 100, b = 3;float c = a / b; // 33.000000// 先使用int类型进行除法运算,再将结果隐式类型转换为floatprintf("c = %f\n", c); // 33.000000c = (float)a / b; // 将a强转为float类型,b也会被隐式类型转换为floatprintf("c = %.6f\n", c); // 33.333332c = (float)(a / b); // 对运算的结果进行强制类型转换printf("c = %f\n", c); // 33.000000// 3. 两个数进行算数运算时,有可能会发生越界,// 此时可以使用强转赋值给一个更大类型的变量int x = 10000, y = 20000;int z = x * y; // 看似没有问题,实际上如果结果很大时可能会越界long int s = (long int)x * y; // 通过类型转换解决越界的问题。return 0;
}
更多推荐
5分钟让你学会C语言类型转换
发布评论