【C语言】:整型提升,算术转换与大小端的介绍

简介: 【C语言】:整型提升,算术转换与大小端的介绍

一. 整型提升

1. 什么是整型提升

C的整型算术运算总是至少以缺省整型类型的精度来进行的。

为了获取足够精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这个转换过程称为整型提升

2. 整型提升的意义

  • 表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度
  • 因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
  • 通用CPU是难以直接实现两个8bit直接相加运算。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或是unsigned int,然后才能送入CPU去执行运算。

3. 整型提升实例

整型的提升是按照数据类型的符号位来提升的

  1. 对于有符号数,发生截断后补符号位
  2. 对于无符号数,发生截断后直接补0。

负数的整型提升:

正数的整型提升:

实例1:

#include <stdio.h>
int main()
{
  char a = 5;
  char b = 126;
  char c = a + b;
  printf("%d\n", c);
  return 0;
}

打印结果:

画图展示计算过程:

实例2:

#include <stdio.h>
int main()
{
  char a = 0xb6;
  short b = 0xb600;
  int c = 0xb6000000;
  if (a == 0xb6)
    printf("a");
  if(b == 0xb600)
    printf("b"); 
  if(c == 0xb6000000)
    printf("c");
  return 0;
}

打印结果:

解释:这是因为a和b都不是int类型,在判断时会发生整型提升(高位补的是1),提升后值会改变,与原16进制不同。但c是int类型,不会改变。

实例3:

#include <stdio.h>
int main()
{
  char c = 1;
  printf("%zd\n", sizeof(c));//1
  printf("%zd\n", sizeof(-c));//4
  printf("%zd\n", sizeof(+c));//4
  return 0;
}

打印结果:

二. 算术转换

前文我们讨论的整型提升是当表达式大小达不到整型大小是才会转换为普通整型进行计算,但是当表达式大小是大于等于整型的呢?

它们在使用时也会发生转换,这种转换叫做算术转换

  • long double
  • double
  • float
  • unsigned long int
  • long int
  • unsigned int
  • int

从下到上类型的大小是从小到大,小类型会往大类型转换。

三. 整型数据存储

1. 大小端的介绍

要了解什么是大小端,首先我们先来观察整型数据在内存中的存储:

#include <stdio.h>
int main()
{
  int a = 20;
  //补码的16进制表示:0x00 00 00 14
  
  int b = -10;
  //补码的16进制表示:0xff ff ff f6
  return 0;
}

我们对a和b进行内存监视:

通过观察,我们可以发现,在内存中存储的a和b的补码是倒着存储的。这是为什么呢?

其实内存在储存数据时一般有两种储存方式:

  • 大端【字节序】存储
    把一个数据的高位字节序内容存放在低地址处,把低位字节序内容放在高地址处,就是大端字节序存储。
  • 小端【字节序】存储
    把一个数据的低位字节序内容存放在低地址处,把高位字节序内容放在高地址处,就是小端字节序存储。

注意

  • 大端字节序和小端字节序描述的是一个数据在内存中进行存储时到底是按什么顺序进行存储的。
  • char类型的字符进行存储时没有大小端序列之分,因为它只有一个字节,而大小端讨论的是字节的顺序,要>=2个字节。
  • 是机器的硬件决定了是大端还是小端存储,与当前编译器无关。

2. 判断当前机器的字节序

#include <stdio.h>
int main()
{
  int a = 1;
  if (*(char*)&a == 1)
    printf("小端\n");
  else
    printf("大端\n");
  return 0;
}

要判断当前机器是大端存储还是小端存储,其实思路非常简单:

我们可以对整数1进行操作,它的二进制为:00000000000000000000000000000001,

转换成16进制为:0x00 00 00 01,

根据上文介绍,a在内存中有两种存储方式:

我们可以发现它们的第一个字节有明显差异,只要我们取出a的第一个字节,判断是00(打印出来就是0)还是01(打印出来就是1),如果打印结果为1,则当前机器是小端存储,若是0,则当前机器是大端存储。

上述代码的输出结果为:

我们可知当前机器是小端字节序存储。

目录
相关文章
|
2月前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
48 10
|
7月前
|
C语言
c语言表达式求值--整型提升
c语言表达式求值--整型提升
|
2月前
|
存储 C语言
C语言:设置地址为 0x67a9 的整型变量的值为 0xaa66
在C语言中,可以通过指针操作来实现对特定地址的访问和赋值。要将地址为 0x67a9 的整型变量值设为 0xaa66,可以先定义一个指向该地址的指针,并通过该指针对该内存位置进行赋值操作。需要注意的是,直接操作内存地址具有一定风险,必须确保地址合法且可写。代码示例应考虑字节序及内存对齐问题。
|
3月前
|
存储 C语言
【C语言基础考研向】04整型进制转换
本文介绍了计算机中整型常量的不同进制表示,包括二进制、八进制、十六进制和十进制,并解释了它们之间的转换方法。以一个32位整型数为例,展示了其在不同进制下的表示形式及计算方法,特别指出在内存观察中常用十六进制,同时提到了小端存储方式对数据的影响。
|
6月前
|
编译器 C语言
C语言学习记录——操作符详解知识点选记(算术操作符、单目操作符、移位操作符、关系操作符、逻辑操作符、条件操作符......)二
C语言学习记录——操作符详解知识点选记(算术操作符、单目操作符、移位操作符、关系操作符、逻辑操作符、条件操作符......)二
53 3
|
6月前
|
存储 编译器 C语言
C语言学习记录——数据的存储(数据类型、类型的基本归类、整型在内存中的存储、大小端介绍、浮点型在内存中的存储)一
C语言学习记录——数据的存储(数据类型、类型的基本归类、整型在内存中的存储、大小端介绍、浮点型在内存中的存储)一
67 2
|
6月前
|
存储 编译器 C语言
C语言学习记录——操作符详解知识点选记(算术操作符、单目操作符、移位操作符、关系操作符、逻辑操作符、条件操作符......)一
C语言学习记录——操作符详解知识点选记(算术操作符、单目操作符、移位操作符、关系操作符、逻辑操作符、条件操作符......)一
44 1
|
6月前
|
存储 C语言
C语言整型详解
C语言整型详解
|
6月前
|
C语言
C语言---单身狗(1)---在一个整型数组中,只有一个数字出现一次,其他数组都是成对出现的,请找出那个只出现一次的数字
C语言---单身狗(1)---在一个整型数组中,只有一个数字出现一次,其他数组都是成对出现的,请找出那个只出现一次的数字
|
6月前
|
存储 编译器 C语言
C语言学习记录——数据的存储(数据类型、类型的基本归类、整型在内存中的存储、大小端介绍、浮点型在内存中的存储)二
C语言学习记录——数据的存储(数据类型、类型的基本归类、整型在内存中的存储、大小端介绍、浮点型在内存中的存储)二
39 0