C语言之整形提升的有关知识

简介: C语言之整形提升的有关知识

整型提升的含义

C语言的整形算术运算总是至少已缺省整型类型的精度来进行,为了获得这种精度,表达式中的字符和短整型操作数,在进行使用前需要转化为普通整形,这种转化称为整型提升。

我的理解即是:一个整形数据有四个字节,32个比特位,而像字符型或者短整型这种数据,他们不够32个比特位,因此需要提升到32位。

进行整型提升的原因

整型算术运算要在计算机cpu内的整型运算器中进行。而整型运算器的操作数字节长度是整形int的字节长度。所以在整型计算时,要将所有数据提升至整形int的字节长度32位,即4字节。

整型提升的过程

首先我们先来看一串代码:

#include<stdio.h>
int main()
{
  char a = -1;
  signed char b = -1;
  unsigned char c = -1;
  char d = 1;
  printf("a=%d,b=%d,c=%d,d=%d", a, b, c,d);
  return 0;
}

再讲解该过程之前,大家先想想输出结果是什么?我猜,有一部分人会认为是-1、-1、-1、1.没错,我在不了解整形提升之前也是这么认为的。

现在我们让代码运行,看看结果是多少:


咦?为什么会出现255呢?仔细看这里的三个变量都是字符型数据,并不是int,但最终以%d的形式输出,难道出现的255是与整型提升有关吗?

下面我们通过了解整型提升的过程来解开这个疑惑!上面我们仅仅了解到了整型提升的定义和原因,那么到底是如何进行提升的呢


以普通字符型进行举例:

char a = -1;

通过前面的学习我么知道数据在内存中是以补码的形式存储,所以我们先写出变量a的补码:

//原码:10000000000000000000000000000001

通过原码写出反码(符号位不变,其他按位取反)

//反码:11111111111111111111111111111110

通过反码写出补码(反码+1)

//补码:11111111111111111111111111111111

然后进行截断,截断的长度为char的长度,一个字节

得到:11111111

下面进行整型提升:规则是(有符号数据类型,最高位代表符号位,则直接补符号位,无符号数据类型,则直接补0)

这里的char,没说是unsigned char吧?因此我们默认他为有符号数

提升后的结果:11111111111111111111111111111111为该数据的补码

由于它是负数,所以我们需要倒推,通过补码找原码

//反码:11111111111111111111111111111110(补码减一)

//原码:1000000000000000000000000001(符号位不变,按位取反)

输出结果即为-1


以有符号字符为例进行举例:

signed char b = -1;

和上面的分析过程几乎一模一样,只不过这里有符号的特征比较明显,在定义的时候明确指出。

以无符号字符为例进行举例:

unsigned char c = -1

和上面一样我们先写出变量c的补码:

//原码:10000000000000000000000000000001

通过原码写出反码(符号位不变,其他按位取反)

//反码:11111111111111111111111111111110

通过反码写出补码(反码+1)

//补码:11111111111111111111111111111111

然后进行截断,截断的长度为char的长度,一个字节

得到:11111111

注意:这里和上面就不同了,由于它是无符号数据类型,所以补0

提升之后的结果为:00000000000000000000000011111111为该数提升之后的补码,由于它是无符号数据类型,因此最高位并不代表符号位,所以它的原码反码补码相同。

输出结果为255


以正数为例进行举例:

char d = 1;

和上面一样我们先写出变量d的补码:由于该数为正数所以它的原码反码补码相同

//原码/反码/补码:00000000000000000000000000000001

然后进行截断,截断的长度为char的长度,一个字节

得到:00000001下面进行整型提升:这里的char,没说是unsigned char吧?因此我们默认他为有符号数提升后的结果:00000000000000000000000000000001为该数据的补码,由于该数为正数所以它的原码反码补码相同

输出结果为1


short类型进行整型提升的时候是如何进行的?

其实它的步骤和char基本相同,差别在于,截断过程,char类型截断8个比特位,因为它是一个字节,而short截断16个比特位,因为它是2个字节。

下面通过具体的示例进行演示:

unsigned short c = -1;

和上面一样我们先写出变量c的补码:

//原码:10000000000000000000000000000001

通过原码写出反码(符号位不变,其他按位取反)

//反码:11111111111111111111111111111110

通过反码写出补码(反码+1)

//补码:11111111111111111111111111111111

然后进行截断,截断的长度为short的长度,两个字节

得到:1111111111111111

注意:由于它是无符号数据类型,所以补0

提升之后的结果为:00000000000000001111111111111111为该数提升之后的补码,由于它是无符号数据类型,因此最高位并不代表符号位,所以它的原码反码补码相同。

输出结果为65535

其他的signedshort和short也是类似的步骤和方法,这里就不过多赘述了。

那整型提升会在哪里用到呢?

还是用上面的变量举例,当字符型数据进行整形运算时,不能直接进行代数和的相加减乘除,必须先进行整型提升,之后再进行代数和的相加减乘除。


以char为例进行举例:

#include<stdio.h>
int main()
{
  char a = -1;
  signed char b = -1;
  unsigned char c = -1;
  char d = 1;
  printf("a=%d\nb=%d\nc=%d\nd=%d\n", a, b, c,d);
  printf("a+b=%d\na+c=%d\na+d=%d\nb+c=%d\nb+d=%d\nc+d=%d\n",a+b, a + c,a+d,b+c,b+d,c+d);
  return 0;
}

输出结果如下所示:


以short为例进行举例:

#include<stdio.h>
int main()
{
  short a = -1;
  signed short b = -1;
  unsigned short c = -1;
  short d = 1;
  printf("a=%d\nb=%d\nc=%d\nd=%d\n", a, b, c,d);
  printf("a*b=%d\na+c=%d\na+d=%d\nb+c=%d\nb+d=%d\nc+d=%d\n",a*b, a + c,a+d,b+c,b+d,c+d);
  return 0;
}

相关文章
|
C语言
【嵌入式C语言】字符转字符串,整形数字转字符串技巧(sprintf函数妙用)
【嵌入式C语言】字符转字符串,整形数字转字符串技巧(sprintf函数妙用)
271 0
|
5月前
|
C语言
C语言---函数--数组---创建一个整形数组,完成对数组的3种操作
C语言---函数--数组---创建一个整形数组,完成对数组的3种操作
|
6月前
|
存储 编译器 程序员
【C语言】整形数据和浮点型数据在内存中的存储
【C语言】整形数据和浮点型数据在内存中的存储
76 0
|
6月前
|
安全 NoSQL 小程序
嵌入式C语言中整形溢出问题分析
嵌入式C语言中整形溢出问题分析
72 0
|
存储 人工智能 编译器
C语言之(有关%d和%u的有关内容,输出方法)(有符号和无符号在内存中的存储情况)(整形无符号数和有符号数是如何进行计算的,整形无符号数和有符号数在循环中的应用举例)
C语言之(有关%d和%u的有关内容,输出方法)(有符号和无符号在内存中的存储情况)(整形无符号数和有符号数是如何进行计算的,整形无符号数和有符号数在循环中的应用举例)
478 0
|
存储 C语言
C语言-数据的存储-整形的存储(8.1)
C语言-数据的存储-整形的存储(8.1)
108 0
|
存储 C语言
【c语言进阶】深度剖析整形数据(二)
【c语言进阶】深度剖析整形数据(二)
105 0
|
存储 C语言
【c语言进阶】深度剖析整形数据(一)
【c语言进阶】深度剖析整形数据(一)
96 0
|
C语言
C语言:整形有序数组中查找具体的某个数(二分查找)
有的人会问,在一个整形的有序数组中,来查找具体的某个数,直接用下面代码就可以了,还有要用什么二分查找,说的有理,但是,下面的那种代码效率不高,
62 0
|
存储 C语言
【c语言进阶】浮点型在内存中的储存是什么样的?会和整形一样吗?快来看看吧!
【c语言进阶】浮点型在内存中的储存是什么样的?会和整形一样吗?快来看看吧!
76 0