为什么编译器将“ char”匹配为“ int”而不是“ short”?


71

我有一个小程序:

#include<iostream>
using namespace std;

void f(int)   { cout << "int\n";   }
void f(short) { cout << "short\n"; }

int main(void){
    char c = 0;
    f(c);
    return 0;
}

它打印int。我觉得,如果这是因为“整数提升”,为什么不是short首选?

我也知道整数提升发生在表达式中(例如A = B)。但是我没有表达对f(),权利的呼吁吗?

如果这是关系到重载解决规则,为什么传递char到F将导致到编译器宁愿intshort

如果我删除的f(int)f(c)会打电话给f(short)

因此,总而言之,我的问题是,它与“整数提升”还是“过载解决规则”有关?又为什么呢


您是否正在尝试解决问题,还是纯粹出于好奇?
卡洛里·霍瓦斯

4
由于没有简短的提升,(有点可疑)原理int被认为是最佳的处理器/寄存器大小,short只是一个压缩的内存布局。因此,使用int(“寄存器”)处理char。假定短减法不会比整数减法更有效。
乔普·艾根

4
@JoopEggen-这不是一个理由(可疑或其他),这是一个设计决策:在C和C ++中,int应该是体系结构的自然大小,因此在没有充分理由偏爱时应使用它其他的东西。
皮特·贝克尔

4
@PeteBecker我想提出设计决定的原因。由于已经有引用参考文献的答案,所以我不希望有法律依据。
乔普·艾根

1
优秀问题+1 !!!
毁灭者

Answers:


67

通过重载解析,(积分)促销优先于其他(积分)转化

隐式转换序列的排名

1)完全匹配:无需转换,左值到右值转换,限定转换,函数指针转换,(自C ++ 17起)用户定义的类类型到相同类的转换

2)促销:积分促销,浮点促销

3)转换:积分转换,浮点转换,浮点积分转换,指针转换,指针到成员转换,布尔值转换,用户定义的派生类到其基类的转换

因此,从char到的升迁int优先于从char到的转化short


什么是促销?你可能会问。这是标准描述的一种特殊转换。

为什么charshort不升职?,您可以继续。整体促销始终是int或更大的类型。没有任何促销short

以下隐式转换被归类为整体促销:

  • 带符号的char或带符号的short可以转换为int;

  • 如果unsigned char或unsigned short可以保持整个值范围,则可以将其转换为int,否则可以将其转换为insigned;

  • 可以根据基础类型将char转换为int或unsigned int:signed char或unsigned char(请参见上文);

  • wchar_t,char16_t和char32_t可以从下面的列表转换为第一种类型,该列表可以保留其整个值范围:int,unsigned int,long,unsigned long,long long,unsigned long long;可以将其基本类型固定的无作用域枚举类型从下面的列表转换为第一种类型,该列表可以保留其整个值范围:int,unsigned int,long,unsigned long,long long或unsigned long long。如果值范围更大,则不应用整体促销;

  • 固定基础类型的无范围枚举类型可以转换为其提升的基础类型;

    (自C ++ 11起)

  • 如果位字段类型可以表示位字段的整个值范围,则可以将其转换为int;如果可以表示位字段的整个值范围,则可以将其转换为unsigned int,否则不应用整数提升;bool类型可以转换为int,值false变为``0'',true变为1。


标准参考(当前标准草案):

[over.ics.scs]§3

[conv.prom]§1


为什么将立即数0视为char而不是整数类型?
shasan

@shasan Literal 0不被视为字符。(通常)“感知”为int。而且,char整数类型。
eerorika

在原始问答中再次看到我的问题。这个问题问为什么函数调用with会0调用int重载。答案解释了“从char到in的提升胜于从char到short的转换”。
shasan

The question asks why the function call with 0 calls the int overload.不,不是。它询问为什么用调用重载函数会c选择int重载而不是shortc不是立即数0;它是一个char左值。原因是一次转换(促销)比另一次转换(而不是促销)
要好。– eerorika

23

来自隐式转换(cppreference):

以下隐式转换被归类为整体促销:

  • [...]
  • char可以转换为intunsigned int取决于基础类型:signed charunsigned char(请参见上文);
  • [...]

因此,如果有函数f(int)f(short),则编译器将首先尝试进行整数提升,如果不可能,则将回退到整数转换

chartoint整数提升(请参见上文),因此编译器将选择它。

如果没有f(int),编译器将无法找到可以进行整数提升的函数,并将回退到整数转换。它找到一个f(short),并且char可以将a转换为short,因此它将选择它。


1
当在整数提升和转换之间建立区别时,为什么在列表本身中使用“转换”一词?这似乎是歧义/混乱的潜在来源,尤其是在引用时。
JAB

@JAB好问题:)我想他们的意思是促销是一种特殊的转换。但是因为它仍然是一种转换,所以他们在某种程度上这样称呼
Rakete1111 '16

他们确实确定积分促销在报价开始时就属于隐式转换类别,因此这是有道理的。
JAB
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.