关于C语言数量类型的转换

今天做了几题关于C语言数据类型转换的题目,感觉自己是懂非懂,于是决定在研究研究。

首先,C语言数据类型的自动转换遵循以下规则(这是经常用到的,还有其他规则这里没有写齐全,可自行百度):

  1. 若参与运算量的类型不同,则先转换成同一类型(更高的),然后进行运算。

  2. 转换按数据长度增加的方向进行,以保证精度不降低。如int型和long型运算时,先把int量转成long型后再进行运算。
    a. 若两种类型的字节数不同,转换成字节数高的类型
    b. 若两种类型的字节数相同,且一种有符号,一种无符号,则转换成无符号类型

  3. 在赋值运算中,赋值号两边量的数据类型不同时,赋值号右边量的类型将转换为左边量的类型。如果右边量的数据类型长度左边长时,将丢失一部分数据,这样会降低精度,丢失的部分按四舍五入向前舍入。

一、我们直接上例题来分析:

#include<stdio.h>  
int main()  
{  
    unsigned int a=5;  
    int b=-10;  
    (a+b>6)?printf(">6"):printf("<=6");   
    return 0;  
}  

结果:
这里写图片描述
这里运用到了2.b的规则,将signed int b,在运算是提升为 unsigned。
b = -10;在计算机中的负数一补码形式存在,就是0xfffffff6,转换为unsigned为4294967286,所以a+b = 5 + 4294967286 = 4294967291;调试也是这个值(结果还有编译器有关)
这里写图片描述

有定义(tip:潜在的级数升级,此处按int输出)

signed char ch = 127;
printf(“%d”,ch+127);

输出结果是254

如果以上改为:

signed char ch = 127;
ch = ch + 127;
printf("ch = %d\n",ch);

输出结果是-2
为什麼是这这样呢?我们再看一个例题:

#include <stdio.h>

int main()
{
    int i = 1,x = 1;
    float j = 3.5, y = 3.5;
    i = i + j;//这里应该是把3.5截取为3,或者1升级为1.0,相加后为4.5,赋给i,截取为int,最终为int类型

    printf("i = %d\n",i);//%d显示: i = 4 
    printf("i = %f\n",i);//%f显示: i = 0.000000,结果错误,所以i不为double/float类型

    printf("x + y = %d\n",x + y);//%d显示:x + y = 0结果错误,所以x+y不为int类型,类型提升为double类型
    printf("x + y = %f\n",x + y);//%f显示:x + y = 4.500000
    return 0;
}

这里写图片描述
根据②③来两个例子,在说明之前强调一点:printf函数中,指定的输出类型和输出表列的类型如果不一致,能通过编译,但是不能正确输出结果。
它们运用的规则为1和3,
1. 若参与运算量的类型不同,则先转换成同一类型(更高的),然后进行运算。
3. 在赋值运算中,赋值号两边量的数据类型不同时,赋值号右边量的类型将转换为左边量的类型。如果右边量的数据类型长度左边长时,将丢失一部分数据,这样会降低精度,丢失的部分按四舍五入向前舍入。

ch = ch + 127; 和i = i + j;
首先存在不同类型的运算,ch + 127; i + j;根据1规则,会提升类型,ch + 127变为int类型,i+j变为double(j为float,i为int,它们最终都会提升为double类型),然后就是不类型的赋值,运用到3规则,ch = ch + 127;(int — >char),i = i + j;(double—>int)然后结合例题③代码得注释去理解。

总结:存在不同类型运算,转换为相同类型(更高的)去运算,这个表达式变成这个更高的类型。并没有真正去改变变量的类型。当混合运算表达式赋值给某个变量时,如果表达式类型和变量类型不一致,表达式类型需要转换为变量类型( 在赋值运算中,赋值号两边量的数据类型不同时,赋值号右边量的类型将转换为左边量的类型。如果右边量的数据类型长度左边长时,将丢失一部分数据,这样会降低精度,丢失的部分按四舍五入向前舍入。)

1. 请问以下类型在32位系统中占用的字节数分别是多少?char、short、int、long、float、double、long double。 答:char:1字节,short:2字节,int:4字节,long:4字节,float:4字节,double:8字节,long double:12字节(在一些编译器中可能会有所不同)。 2. 请问以下代码输出的结果是什么? ```c int a = 100; char b = (char)a; printf("%d,%d", a, b); ``` 答:输出结果是“100,100”。char类型转换时会截取a的低8位,因此b的值也是100。 3. 请问以下代码输出的结果是什么? ```c int a = 100; char b = (char)a; int c = (int)b; printf("%d,%d,%d", a, b, c); ``` 答:输出结果是“100,100,100”。在对char类型进行类型转换时,会将其扩展为int类型,因此c的值也是100。 4. 请问以下代码输出的结果是什么? ```c int a = 100; char b = (char)a; int c = (unsigned char)b; printf("%d,%d,%d", a, b, c); ``` 答:输出结果是“100,100,100”。在对char类型进行类型转换时,如果是无符号类型,会先将其扩展为int类型,再进行类型转换,因此c的值也是100。 5. 请问以下代码输出的结果是什么? ```c int a = -100; unsigned int b = (unsigned int)a; printf("%d,%u", a, b); ``` 答:输出结果是“-100,4294967196”。在对有符号类型进行类型转换时,如果其值为负数,会先将其转换为对应的无符号数,再进行类型转换。 6. 请问以下代码输出的结果是什么? ```c int a = -100; unsigned char b = (unsigned char)a; printf("%d,%u", a, b); ``` 答:输出结果是“-100,156”。在对有符号类型进行类型转换时,如果其值为负数,会先将其转换为对应的无符号数,再进行类型转换。因为char类型是无符号类型,所以b的值为156,它是-100在[0,255]范围内的补码表示。 7. 请问以下代码输出的结果是什么? ```c unsigned int a = 0xffffffff; int b = (int)a; printf("%u,%d", a, b); ``` 答:输出结果是“4294967295,-1”。在对无符号类型进行类型转换时,如果其值为最大值(即全1),会先将其转换为对应的有符号数,再进行类型转换。 8. 请问以下代码输出的结果是什么? ```c float a = 3.14f; int b = (int)a; printf("%f,%d", a, b); ``` 答:输出结果是“3.140000,3”。在对浮点类型进行类型转换时,会将其小数部分直接截取,不会四舍五入。 9. 请问以下代码输出的结果是什么? ```c int a = 0x12345678; char *p = (char*)&a; printf("%x,%x,%x,%x", p[0], p[1], p[2], p[3]); ``` 答:输出结果是“78,56,34,12”。因为CPU的字节序是小端模式,所以低地址存放的是数据的低位字节。 10. 请问以下代码输出的结果是什么? ```c int a = 0x12345678; int b = *((int*)((char*)&a + 1)); printf("%x", b); ``` 答:输出结果是“345678”。因为将指针加1后,指向的是a的次高位字节,再将其转换为int指针,就可以得到a的次高位和高位字节组成的整数。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值