最近在看模板元编程的时候遇到这么一件事: char +(or -) char => int short +(or -) short =>int 为什么两个短整型相加减的类型是一个int呢?

这里涉及到一个概念 叫做类型提升,那什么是类型提升,为什么要进行类型提升,于是我展开了实验。
我的代码如下:

template <typename T1, typename T2>
struct plus_result {using type = decltype(std::declval<T1>() + std::declval<T2>());
};template <typename T1, typename T2>
using plus_result_t = plus_result<T1, T2>::type;int main() {plus_result_t<char, char> a;plus_result_t<char, short> b;plus_result_t<short, short> c;std::cout << typeid(a).name() << std::endl;std::cout << typeid(b).name() << std::endl;std::cout << typeid(c).name() << std::endl;return {};
}

输出:

    iii

下面是x86-64 gcc 12.2生成的汇编

看一下下面一段代码,结果会是多少:

char b = 100;
char c = 200;
auto i = b + c;
printf("%s\n", typeid(i).name());   // what is type of i?
printf("%d\n", i);                  // what is value of i?
printf("%d", sizeof i);             // how long is i ?

输出结果为:

i
44
4

x86_64指令集masm汇编如下:

 mov    BYTE PTR [rbp-0x1],0x64     ;0x64mov    BYTE PTR [rbp-0x2],0x64     ;0xc8movsx  edx,BYTE PTR [rbp-0x1]movsx  eax,BYTE PTR [rbp-0x2]add    eax,edxmov    DWORD PTR [rbp-0x8],eax

将十六进制立即有符号数100(0x64 -> 0110 0100) 放入[b]所指向的对象b的内存的第1个字节
将十六进制立即有符号数200(== -56, -56是有符号数,计算机中以其补码存放(1100 1000 == c8)) 放入[c]所指向的对象c的内存的第1个字节

从b中取出一字节放到32位dx寄存器edx中,同样从c中取出1字节放到32位ax寄存器eax中
这里使用movsx(带符号扩展指令),当计算机中存放一个带符号数时,符号位位于最高位。对于正数而言,会把寄存器中扩展后高位置为0,其效果和movzx(零扩展指令)一样。而对于负数,高位会被全部置为1。
因此寄存器edx为0000 0000, 0000 0000, 0000 0000, 0110 0100 -> 0x00000064; eax中数据不再为1101 0110,而是1111 1111, 1111 1111, 1111 1111, 1100 1000 -> 0xFFFFFFC8 加和为 1(舍弃), 0000002c

加和后寄存器eax中值为0x0000002c,取其双字(4字节)放到对象i中,i为44

生成汇编,i是一个4字节

为什么会生成这样的汇编呢?

C99/C11标准之常用算术转换一章:
If the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

自动类型转换的基本规则:

  1. 在表达式中,char 和 short 类型的值,无论有符号还是无符号,都会自动转换成 int 或者 unsigned int(如果 short 的大小和 int 一样,unsigned short 的表示范围就大于 int,在这种情况下,unsigned short 被转换成 unsigned int)。因为它们被转换成表示范围更大的类型,故而把这种转换称为“升级(promotion)”。

  2. 按照从高到低的顺序给各种数据类型分等级,依次为:long double, double, float, unsigned long long, long long, unsigned long, long, unsigned int 和 int。这里有一个小小的例外,如果 long 和 int 大小相同,则 unsigned int 的等级应位于 long 之上。char 和 short 并没有出现于这个等级列表,是因为它们应该已经被升级成了 int 或者 unsigned int。

  3. 在任何涉及两种数据类型的操作中,它们之间等级较低的类型会被转换成等级较高的类型。

  4. 在赋值语句中,= 右边的值在赋予 = 左边的变量之前,首先要将右边的值的数据类型转换成左边变量的类型。也就是说,左边变量是什么数据类型,右边的值就要转换成什么数据类型的值。这个过程可 能导致右边的值的类型升级,也可能导致其类型降级(demotion)。所谓“降级”,是指等级较高的类型被转换成等级较低的类型。

而且现在32位或者64位CPU一次处理32位或64位数据,对于低于其的数据访问意义不大。

为什么char+char为int类型 C/C++类型提升相关推荐

  1. 黑马程序员C语言基础(第八天)复合类型(自定义类型)(结构体)、共用体(联合体)、枚举enum、 typedef

    黑马程序员C语言基础(第一天) 黑马程序员C语言基础(第二天) 黑马程序员C语言基础(第三天) 黑马程序员C语言基础(第四天)数据类型 黑马程序员C语言基础(第五天)运算符与表达式.程序流程结构.数组 ...

  2. JAVA实体类不要使用基本类型,基本类型包含byte、int、short、long、float、double、char、boolean...

    由于JAVA的基本类型会有默认值,例如当某个类中存在private  int age;字段时,创建这个类时,age会有默认值0.当使用age属性时,它总会有值.因此在某些情况下,便无法实现age为nu ...

  3. java中char类型转换成int类型的方法

    java中,需要对输入进行一些判断,比如需要输入的是数字,而用户输入了字符,那么就会报错,因此用char或者String类型接收输入的数据就不会报错,但是问题来了:如何让输入的char或者String ...

  4. java中char类型转换成int类型的两种方法

    java中char类型转换成int类型的两种方法 方法一: 第一种利用Integer包装类的方法Integer.parseInt Copychar ch = '9'; if (Character.is ...

  5. C语言 指针数组-字符指针数组整型指针数组 char*s[3] int*a[5] 数组指针int(*p)[4]

    基本介绍 1.指针数组:由n个指向整型元素的指针而组成,里面存放指针 Int *ptr[3]; 2.地址: ptr[i]:元素地址 &ptr[i]:指针地址 图示 代码: 内存布局: 代码 # ...

  6. 一次事故,我对MySQL时间戳存char(10)还是int(10)有了全新的认识

    摘要:char类型字段想走索引的话,必须用引号括起来.如果是时间戳等类型的纯数字,建议还是存为int型吧. 本文分享自华为云社区<一次事故,我对MySql时间戳存char(10)还是int(10 ...

  7. MySql 时间戳存char还是存int?

    一次小事故,让我对时间戳存char还是存int有了深刻的印象. 生产环境的sql条件涉及到时间戳字段的大小比较(between and),当时设计的时间戳类型是char(10),结果当数据量达到200 ...

  8. 给定C语言数据结构,给定C语言的数据结构struct T { int w; union T { char c;int i;double d;)U; };...

    给定C语言的数据结构struct T { int w: union T { char c:int i:double d:)U: }: 更多相关问题 HBV感染者的血清用电镜观察可见到_________ ...

  9. 读取二代身份证上的相片,函数GetBmp(char * Wlt_File,int intf) 怎么用?

    今天看到很多网友对于读取二代身份证上的相片遇到了麻烦,GetBmp(char * Wlt_File,int intf) 这个函数不知道怎么用.下面是我做的小实例,仅供参考,希望能帮到大家. publi ...

最新文章

  1. 2021年大数据Spark(一):框架概述
  2. 【编程开发】Python隐藏属性——使用双下划线标识私有属性,外部不可直接访问...
  3. 非索引查询如何提高效率_Python数据分析:数据库索引如何提高效率?
  4. canopen c++程序编写_JAVA、C、C++、Python同样是高级语言,为什么只有C和C++可以编写单片机程序?...
  5. 互联网公司前端初级Javascript面试题
  6. php 支付宝付款接口测试
  7. Asterisk标准通道变量
  8. redis -- 学习
  9. Java教程:Java程序的运行过程(执行流程)分析
  10. bzoj 2751: [HAOI2012]容易题(easy)
  11. [转载] python将int转为string_python – 在Pandas中将列名从int转换为string
  12. 色不迷人人自迷,情不伤人人自伤
  13. word文本框中插入文本框_在Word 2007中快速将文本翻译成另一种语言
  14. N卡怎么修改录屏文件保存位置
  15. 会议安排问题(贪心算法)
  16. 火车头+php教程,dede使用火车头采集视频教程
  17. Isaac-gym(6):环境创建、模型载入、actor设置等
  18. 新学:DES加密 小知识点(S盒,初始置换)
  19. drat中const和final
  20. 云服务器该如何选择?

热门文章

  1. 如何制作抖音卡点视频,使用预设制作酷炫转场
  2. 发那科机器人没有码垛指令_FANUC 机器人码垛编程详细讲解
  3. VMware-KVM安装
  4. python爬取boss直招_简易python爬虫爬取boss直聘职位,并写入excel
  5. 大数据分析:数字化企业转型的关键
  6. 灵魂碎片的收集(构造)
  7. 使用微信PC端的截图dll库实现微信截图功能(C++ Builder实现)
  8. 岛屿数量问题(C实现)
  9. peewee和peewee_async常用汇总(持续更新)
  10. 面试时,问你有什么缺点,到底该怎么回答?我总结了“3个3”