深入理解C语言中的类型转换

隐式转换

基本类型转换

整形提升

表达式计算时,整型会首先提升到int类型,当int类型表示的范围不够时,会提升为unsigned int类型。c语言中可以进行整型提升的包括bool,char,short及其对应的无符号类型。下面例子中,不管是bool,char还是short类型,在进行算术运算时,运算结果大小都是4个字节,这是因为编译器会默认对这些整型进行提升,转为4个字节再进行运算。

int main()
{
    bool b1 = true;
    bool b2 = true;
    // output: 4 2
    cout << sizeof(b1 + b2) << " " << b1 + b2 << endl;

    char c1 = 'a';
    char c2 = 'b';
    // output 4 195
    cout << sizeof(c1 + c2) << " " << c1 + c2 << endl;

    short s1 = INT16_MAX;
    short s2 = 1;
    // output 4 32768
    cout << sizeof(s1 + s2) << " " << s1 + s2 << endl;

    return 0;
}

算术转换

  • 整型和浮点数相加得到浮点型;
  • 有符号整型和有符号整型相加得到其中较大的有符号整型;
  • 无符号整型和无符号整型相加得到其中较大的无符号整型;
  • 有符号整型和无符号整型相加得到较大空间的类型,如果有符号整型空间大,则结果为有符号整型,如果无符号整型空间大,则结果为无符号整型,如果有符号整型和无符号整型空间相等,则结果为无符号整型。

总结来说,算术转换会往较大空间类型的方向转换;如果空间一样,则会往浮点型或者无符号方向转换。

int i1 = INT32_MAX;
long long ll1 = 1;
// output 8 2147483648
cout << sizeof(i1 + ll1) << " " << i1 + ll1 << endl;

unsigned int ui1 = 1;
// output 4 2147483648
cout << sizeof(i1 + ui1) << " " << i1 + ui1 << endl;

int i2 = 1;
// output 4 -2147483648 整数溢出
cout << sizeof(i1 + i2) << " " << i1 + i2 << endl;

转换为void*指针

任何指针类型都可以隐式转换成void*类型,反之不成立。

int a = 0;
int* pa = &a;
void* pb = pa;    // 正确
pa = pb;          // 编译错误

数组转换为指针

任意一个数组类型都可以隐式转换成数组元素对应类型的指针。

int a[10];
int* pa = a; 

数组和指针是有区别的,数组初始化,赋值等方式和指针是不同的,额外要注意的一点是,sizeof(a)结果是40,而sizeof(pa)结果不是10,而是4(具体和机器是相关的),因为后者求的是指针的大小,前者求的是整个数组的大小。

转换成bool类型

C语言中任意整型、浮点型、字符类型和相应指针类型都可以隐式转换为bool类型,当这些类型的值为0时,转换为false;否则转换为true。

int a = 10;
bool b = a;     // b 为 true
int* pa = NULL;
b = pa;         // b 为fasle

转换成常量

任意非常量的指针或者引用都可以转换成对应的常量指针或者引用,反之是不行的。

int a = 10;
const int* pa = &a;   // &a为非常量指针,转换为常量指针pa
const int& ra = a;    // ra为对a的非常量引用

显示转换

第一部分中提到了C语言中基本类型之间的转换以及任意指针转换为void指针,这些转换都可以隐式地进行,编译器默认帮助开发者操作,不会报错。然而,对于void指针转换为某个具体类型的指针或者任意两种不是void类型指针之间的转换来说,编译器都会抛出错误。需要明确的一点是,C语言中任意类型指针之间都是可以完成转换的,只不过编译器觉得这个转换很不安全,不会帮我们暗地里操作,需要程序开发者个人判定安全性,使用显示转换。有人可能会觉得第一部分中的转换也很不安全,比如double转为int,会使得数值损失精度,事实确实如此,但相比任意指针间的转换来说,这种转换的风险小得多,因此对于第一部分的情况,编译器支持默认转换。

int a = 0;
void* pa = &a;
int* pb = (int*)pa;
// 正确,输出0
cout << *pb << endl;

// 正确,输出空,因为a为0,其第一个字节为0,在char型变量中,表示空
char* pc = (char*)pb;
cout << *pc << endl;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值