类型转换主要可以笼统的分为两大类:隐式类型转换与显式类型转换。
注意:不论是隐式类型转换还是显式类型转换,在进行算术类型转换时,高精度转为低精度都会有精度损失,低精度转为高精度是没有。比如在有符号的char类型在与int类型进行转换时。将有符号char类型转换成int类型时,值是无损失的(不会发生变化的)。而int类型赋值给有符号char类型时其实进行的是截断式赋值。 例子:
signed char sc1 = -128; //结果i1值为-128,将10000000自动扩展为111...10000000 int i1 = sc1; int i2 = -1073741823; //结果sc2值为1,发生了截断式赋值,将11000...00000001截断为00000001 signed char sc2 = i2;
隐式类型转换
隐式类型转换不需要程序员介入,是自动进行的。通常我们注意的比较多的换转换通常是算数类型的隐式类型转换。
算数类型的隐式类型转换
在表达式求值时,算数转换的规则定义了一套类型转换的层次,其中的大方向是将运算对象转换成最宽的类型。具体规则如下:
-
首先会进行整形提升,如果运算对象双方是
bool、char、signed char、unsigned char、short、与unsigned short
等可以不损失精度的放入int类型中,它们就会提升为int类型。如果它们中有不能用int类型无损存储的,比如unsigned int、long
等类型,则会将较小的一方提升为精度较高一方的类型。 -
如果运算对象双方一个为无符号类型,一个为有符号类型,并且无符号类型不小于有符号类型,则将带符号的运算对象转换成无符号的。
-
如果带符号类型大于无符号类型,则结果需要依赖机器。如果此带符号类型可以无损存储此无符号类型,则将无符号类型转换成带符号类型。否则,结果反之。比如两个运算对象分别是
long
与unsigned int
类型,则怎么转换就需要依赖机器中long
类型占用空间是否比int
多。
总结:表达式求值在根据
double>float>int
之类的隐式类型转换后求出来的值在赋值时还会再进行一次隐式类型转换。例如:int c=5; char d='0'; char a = c + d;
其他隐式类型转换
-
数组名转成指针:例如
int a[10]; int *p=a;
中将数组名转成指针,但是当数组被用作decltype
关键字的参数或者作为取地址符(&)、sizeof
以及typeid
等运算符的运算对象时,上述转换不会发生; -
指针的转换:比如,第一、常量正数值0或者字面值常量nullptr能转换成任意指针类型;第二、指向任意非常量的指针能转换成
void *
;第三、指向任意对象的指针能转换成const void*
; -
转成
bool
类型(通常在判断表达式中); -
转换成常量:允许将非常量类型赋值给常量;
显式类型转换
显式类型转换也叫作强制类型转换,除非必须,否则不建议使用。并且在这方面,c语言提供的强制类型转换是及其不完善的,c++对与强制类型转换比之要完善很多,不过依然不建议使用。
整数类型转换机器码操作
- 同位宽的无符号与有符号的整数类型进行转换时,内存中机器码形式不变,变得是机器码的解读方式,以补码形式进行解读还是无符号数形式进行解读。
- 在进行扩展位宽的整数类型转换时,无符号数进行零扩展,有符号数进行符号扩展。(这两种方式都能保证扩展后原值不变,原理可参考补码原理)
- 在进行截断位宽的整数类型转换时,采用截断式转换。
- 同时进行无符号与有符号和不同位宽类型转换时,首先进行位宽变换。
#include <stdio.h>
//#include <stdlib.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, int len) {
int i;
for (i = 0; i < len; i++)
printf(" %.2x", start[i]);
printf("\n");
}
void test() {
/* $begin extend */
short sx = -12345; /* -12345 */
unsigned short usx = sx; /* 53191 */
int x = sx; /* -12345 */
unsigned ux = usx; /* 53191 */
unsigned uy = sx; /* Mystery! */
// 16位有符号数-12345与其机器码
printf("16位有符号数-12345与其机器码: %d:\t", sx);
show_bytes((byte_pointer) &sx, sizeof(short));
// 将16位有符号数-12345转换成16位无符号数后其值与机器码
printf("将16位有符号数-12345转换成16位无符号数后其值与机器码: %u:\t", usx);
show_bytes((byte_pointer) &usx, sizeof(unsigned short));
// 将16位有符号数-12345扩展成32位有符号数后其值与机器码
printf("将16位有符号数-12345扩展成32位有符号数后其值与机器码: %d:\t", x);
show_bytes((byte_pointer) &x, sizeof(int));
// 将16位无符号数53191扩展成32位无符号数后其值与机器码
printf("将16位无符号数53191扩展成32位无符号数后其值与机器码: %u:\t", ux);
show_bytes((byte_pointer) &ux, sizeof(unsigned));
// 将16位有符号数-12345转成32位无符号数后其值与机器码
printf("将16位有符号数-12345转成32位无符号数后其值与机器码: %u:\t", uy);
show_bytes((byte_pointer) &uy, sizeof(unsigned));
/* $end extend */
}
int main(){
test();
return 0;
}
运行结果如下:
xhy@ubuntu:~/c_learn/datatype_int_convert$ ./test
16位有符号数-12345与其机器码: -12345: c7 cf
将16位有符号数-12345转换成16位无符号数后其值与机器码: 53191: c7 cf
将16位有符号数-12345扩展成32位有符号数后其值与机器码: -12345: c7 cf ff ff
将16位无符号数53191扩展成32位无符号数后其值与机器码: 53191: c7 cf 00 00
将16位有符号数-12345转成32位无符号数后其值与机器码: 4294954951: c7 cf ff ff
今天的文章c语言类型转换详解_c语言中强制类型转化格式分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/88722.html