【问题标题】:Why does applying bitwise NOT to a char yield an int? [duplicate]为什么将按位 NOT 应用于 char 会产生 int? [复制]
【发布时间】:2016-05-05 16:18:50
【问题描述】:

在我的笔记本电脑上,运行以下代码:

#include <iostream>
using namespace std;

int main()
{
    char a;
    cout << sizeof(~a) << endl;
}

打印4

我预计~a 的结果是char,但显然它是int

这是为什么呢?

【问题讨论】:

  • 虽然这可能是一个骗局(正在寻找一个),但我没有得到反对。如果不了解积分提升规则,这对我来说搜索起来并不容易。
  • This 一开始还不错。 OP:你觉得这样就够了?
  • 糟糕,没有注意到sizeof

标签: c++


【解决方案1】:

~ 是一个算术运算符(按位非),a 正在从 signed char 提升到 int(在许多实现中是 sizeof(int) == 4)。解释见下文:

http://en.cppreference.com/w/cpp/language/implicit_conversion#integral_promotion

小整数类型(如 char)的 prvalues 可以转换为 较大整数类型(例如 int)的纯右值。尤其, 算术运算符不接受小于 int 的类型 参数,并且积分提升在之后自动应用 左值到右值的转换(如果适用)。这种转换总是 保留价值。

【讨论】:

  • 感谢您的回答!我想我明白了。但我想知道为什么它在 c++ 中以这种方式实现。
  • @HanQiu 因为 C 也是这样做的,而且 C++ 应该是广泛兼容的。现在我不知道为什么 C 会这样做。也许有些int是最快的整数类型原因”
  • @BaummitAugen 关于int 的任何证据是最快的?而且我们现在大多数人都使用64位机器,32位int仍然是最快的吗?
  • @HanQiu int 在创建 C 时应该是机器上的自然整数类型。早在 70 年代,64 位机器可能并不重要。 ;)
  • 同样在汇编中按位和算术运算通常至少涉及一个寄存器,当您将值移动到寄存器时,您必须提升它(除非您正在为 8 位处理器编译) .因此,当您有多个操作时,将提升作为第一步是有意义的,以获得高效的机器代码结果。
【解决方案2】:

标准规定 (§[expr.primary]/10):

~的操作数应该是整数或无范围的枚举类型;结果是其操作数的反码。进行整体促销。结果的类型是提升的操作数的类型。

“整体促销”是指(§[conv.prom]/1):

boolchar16_tchar32_twchar_t 以外的整数类型的纯右值,其整数转换等级 (4.13) 小于 int 的等级可以转换为type int if int 可以表示源类型的所有值;否则,可以将源纯右值转换为unsigned int 类型的纯右值。

在您的情况下,a 的类型为 char,其转化排名低于 int1 的排名,因此它被提升为 int 或 @987654333 @,两者的大小相同(在您的实现中显然是 4)。

至于为什么会这样做:我认为很大程度上是因为它大大简化了语言定义和编译器。不必为几乎每种类型单独生成代码,而是尽力将所有内容分解为几种类型,并且大多数代码仅针对这些类型生成。情况不再如此(现在我们有多个大于int 的类型),但在 C 还年轻的时候,整数类型是:charshortint(和无符号版本的那些),所以所有其他类型都被提升为int,所有操作任何东西的代码都是用ints完成的。

请注意,这也适用于函数调用等:在 C 的早期版本中,没有函数原型,因此 charshort 类型的任何参数在传递给函数之前也被提升为 int .

浮点类型遵循相同的基本思想:在大多数情况下(包括将它们传递给函数)floats 被提升为double,所有实际处理都在doubles 上完成(之后如有必要,您可以转换回float


  1. 如果您真的也想要报价(§[conv.rank]:

1.3 除 bool、char16_t、char32_t 或 wchar_t 以外的整数类型的纯右值,其整数转换等级 (4.13) 小于 int 的等级,如果 int 可以表示所有值,则可以将其转换为 int 类型的纯右值源类型;否则,源纯右值可以转换为无符号整数类型的纯右值。
[...]
1.6 char 的秩应等于signed char 和unsigned char 的秩。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    • 2020-11-08
    • 2020-10-11
    • 1970-01-01
    相关资源
    最近更新 更多