C语言中的整数类型及类型转换(为什么强制类型转换值发生改变?带你从机器码的角度分析)
文章目录
1.首先看一下C语言整数数据类型范围
注意:数值范围没有负数的则为无符号位的数,有负数范围的则为有符号位的数
- 输出时:
- %u无符号十进制整数
- %d有符号十进制整数
- %0无符号八进制
- %x无符号十六进制整数
- 在计算机中数据都是以补码形式存储的,%u无符号输出,没有符号位,是正数;%d有符号输出,有符号位,
符号位在最高位
2.有符号数和无符号数的转换(相同字长)
- 我们在C语言中常利用强制类型转换,有时候强制类型转换的结果却不是我们希望得到的,因为计算机存储数据是以补码形式存储的
- 有时候强制类型转换可能会改变数值,可能是数据类型有无符号位导致的
- 无符号位是正数就不用转换,因为正数原码=补码
- 有符号位的数,根据符号位是0还是1来判断是否需要转换,那么如果符号位是1,是负数就要转换,数值当然会不同
- 现在我们看一段代码来看一下这种特殊情况:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
short x=-4321;
unsigned short y=(unsigned short)x;
printf("x=%d,y=%u\n",x,y);
return 0;
}
- 我们可以看出y值和x值没有一点关系,咱们将其都转换成二进制,我们便知道了为什么。且看二进制转换表
我在自己的电脑上测试了一下,由于电脑是64位,所以转换就是64个二进制数,至于为什么16位往左所有数都是1,这就涉及到了符号扩展
去掉符号位补码转原码为下图所示:
- 其中x为补码,y为无符号二进制真值,正数的补码=原码。因为数在计算机中都是以补码形式存储的,正数的补码是自身,负数的补码需要转换
- unsigned short 为无符号整数,所以它没有符号位,全是数值位,是正数
- 而short是有符号的整数,有符号位,符号位在最高位,需要将补码转换成原码输出
- 可以看出,强制类型转换结果相应位置的值不变,仅仅只改变了解释这些位的方式,是short解释,还是unsigned short 解释,这两种方式
同样的我们再看一段代码仔细揣摩揣摩:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
unsigned short x=65535;
short y=(short)x;
printf("x=%u,y=%d\n",x,y);
return 0;
}
- 相应位置数值相等,但是表示结果不同,那是因为解释方式不同;unsigned short 和short两种解释方式
3.不同字长整数之间的转换
3.1 大字长变量向小字长变量强制类型转换
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int x=165537,u=-34991; //int 4B
short y=(short)x,v=(short)u; // short 2B
printf("x=%d,y=%d\n",x,y);
printf("u=%d,v=%d\n",u,v);
return 0;
}
- 当大字长变量向小字长变量强制类型转换时,系统将多余的高位字长部分直接截断舍去,低位直接赋值
3.2 小字长变量向大字长变量强制类型转换
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
short x=-4321; // short 2B
int y=x; // int 4B
unsigned short u=(unsigned short)x;
unsigned int v=u;
printf("x=%d,y=%d\n",x,y);
printf("u=%u,v=%u\n",u,v);
return 0;
}
- 这里我们转换成十六进制输出
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
short x=-4321; // short 2B
int y=x; // int 4B
unsigned short u=(unsigned short)x;//无符号数,直接取当前数据类型长度的原数字x的补码长度,不用转换成原码输出
unsigned int v=u;
printf("x=%d,y=%d\n",x,y);
printf("u=%x,v=%u\x",u,v);
return 0;
}
-
我们发现,短字长整数到长字长整数的转换,不仅要使相应的位置相等,
高位部分还会扩展为原数字的符号位
-
注意:char类型为8位ASCII码整数,转换成int型时,高位部分补0即可。ASCII码由7位二进制数字组成