【问题标题】:Sum of two chars in C/C++C/C++ 中两个字符的总和
【发布时间】:2013-10-19 21:15:59
【问题描述】:

在 C/C++ 中,当我想查找两个字符的总和时 - 我得到 int 的结果。
例如:

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

打印

1 + 1 = 4

为什么?

【问题讨论】:

  • operator+ 不提供两个字符。
  • 你期待什么输出?
  • @AustinBrunkhorst 看来我看错了,我很抱歉,这是正确的
  • @mbratch 我认为字符的总和必须是字符。 (1 + 1 = 1)

标签: c++ c


【解决方案1】:

因为虽然ab 都属于char 类型,所以表达式a + b 属于int 类型。每当您使用 char 类型进行数学运算时,它们都会在进行实际计算之前转换为 int。

【讨论】:

  • 他知道。他在问为什么
  • 因为标准是这样说的。还有什么其他原因?
  • 标准以这种方式定义它一定是有原因的;)查看this link(或下面的我/其他答案)以获取有关整体促销的更多信息。我怀疑,标准定义这一点的原因是性能:它在仅定义 32b 或 64b 本机整数类型的架构上节省了额外的屏蔽和标志提升指令。
  • @LeeDanielCrocker:根据 Rationale for International Standard-Programming Languages-C,修订版 5.10,2003 年 4 月,“在 K&R 的发布和 C89 的开发之间,存在严重的分歧在整数提升规则的演变过程中发生过”和“输入整数常量的规则是根据 C89 委员会对整数提升规则的审议精心制定的。”很明显,整数晋升规则和委员会对它们进行审议的背后有一段历史,它们是有原因的。
  • @LeeDanielCrocker 好的,那么告诉我们,为什么标准对于这么简单明了的事情如此愚蠢 -> 在对 int 进行实际操作后自动将结果转换回 char?
【解决方案2】:

1) 这只是打印出文本字符串“something + something else”:您实际上并没有添加任何东西:printf("%d + %d = %d\n",..)

2) sizeof(&lt;some char&gt;) 将始终为“1”。这就是“sizeof()”的意思——它永远不可能是除了“1”之外的任何东西。

3) 是的,添加类型“char”(它是一个整数子类型)将给出一个整数结果。

更多详情:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

char 类型,有符号和无符号整数类型,以及 枚举类型统称为整数类型。整数 而真正的浮动类型统称为真正的类型。

【讨论】:

    【解决方案3】:

    因为如果不提升,结果可能会溢出

    单字节字符不能保存大于255(无符号)+127(有符号)的值。当您将两个实例相加时,总是有溢出的可能性,即结果超过 255。这意味着它不能存储在 单个字节中。因此使用 int 不能超过两个字符或字节的最大总和。

    【讨论】:

    • 但是添加两个 int 值也会溢出。因此,根据这种推理,int 值应该被提升为更大的值以供添加。那不会发生。此外,C 和 C++ 都没有将 char 值限制为 8 位。大多数实现都这样做,但要求是至少 8位。
    • 我记得很久以前在某个地方读过。它仅在转换为整数时特定于字符。以下讨论这是一种观点,尽管我同意它不适用于推广所有类型。 stackoverflow.com/a/4814889/986760。一个字节的 char 仅用作示例,尽管假设 int 大于 char 是合理的。
    • 对于它的价值,这是 Raymond Chen 为溢出是可疑原因之一的讨论 blogs.msdn.com/b/oldnewthing/archive/2004/03/10/87247.aspx
    【解决方案4】:

    查看 ANSI C 规范,here 是解析加法表达式的方式。

    关于如何解析以及如何读取操作数的详细说明:

    涉及指针和整数的加法运算符的整数操作数指定为 TypeIs_unsigned_long。任何整数类型都可以通过隐式转换的方式转换为 TypeIs_unsigned_long,所以这个规范等同于标准的规范。使用 TypeIs_unsigned_long 的主要原因是 OIL 不允许将集合作为类定义中的操作数规范,但次要原因是这种方法减少了编译器数据库中的运算符总数。

    【讨论】:

    • 嗯,引用的文字与在标准C中添加两个char值无关。
    • 同意,引用更关心添加整数和指针;答案有点模糊。但是,该链接跳转到加法运算符语义的定义,其中包括其类型,以及其他答案中提到的积分提升(eli-project.sourceforge.net/c_html/c.html#s6.2.1.1)。
    【解决方案5】:

    第 4.5 节整体促销

    除 bool、char16_t、char32_t 或 wchar_t 其整数转换等级 (4.13) 小于 如果 int 可以表示所有,则 int 可以转换为 int 类型的纯右值 源类型的值;否则,源纯右值可以是 转换为 unsigned int 类型的纯右值。

    标准在所谓的“常用算术转换”第 5 条 [expr] 第 10 点中规定了转换:

    许多二元运算符需要算术或 枚举类型导致转换并产生结果类型 类似许多期望算术操作数的二元运算符或 枚举类型导致转换并产生类似的结果类型 大大地。目的是产生一个通用类型,这也是 结果。这种模式称为通常的算术转换, 其中定义如下:方式。目的是产生一个共同的 type,也是结果的类型。这种模式称为 常用的算术转换,定义如下:

    除非为少数选择类型。 long double, doublefloat

    否则,积分促销 (4.5) 应在两者上执行 操作数.59

    (char)+(char) 产生一个 int。

    还要注意 char+char 很棘手。 char 可以根据实现有符号或无符号;因此对于正常值,结果可能很容易溢出,这可能是为什么它没有作为例外包含在标准中的原因。

    【讨论】:

    • 不过,您需要另一个报价,这只是说促销是可能的,您需要另一个来真正引起它。
    • 还要注意 OP 是(错误地?)在做 sizeof(a), sizeof(b), sizeof(a + b)),而不是 (char)+(char)
    【解决方案6】:

    这种提升的原因是历史性的:当 C 被发明时,40 多年前,处理器在单一整数类型上进行数学运算;您可以存储较小的类型,但没有字节级算术。所以提升规则反映了当时的现实:小于处理器整数类型的类型将被硬件提升为该整数类型。当然,您可以在软件中进行数学运算(long 通常是这样实现的),但这会慢得多(就像 long 通常那样)。

    【讨论】:

    • 40 年了 ;-) (1972)
    • @Jens - 我就是这么说的(偷偷编辑;感谢您的更正)
    • 快 50 年 ;-)
    【解决方案7】:

    这就是 C 和 C++ 的工作方式:在对 char 类型的变量执行任何操作之前,编译器首先将它们转换为 int。这称为整数提升。注意:anything 由 C 和 C++ 标准定义;它不包括sizeof,但包括大多数其他操作(除了sizeof 之外,我不记得有任何例外)。

    至于这种可能令人惊讶的行为的原因 - 这可能是在古代做出的决定,导致现代 C 和 C++ 从那时起就以这种方式行事,以实现兼容性。

    人们经常有大量chars 数组,它们不是真正的字符,而是很小的数字。在使用这些进行算术运算时,很自然地会将每个数字自动转换为int 并对它们进行算术运算,因为int 是算术运算最快的类型。还有一个令人愉快的副作用,即在促销生效时溢出不太可能发生(当ab 属于char 类型时,请考虑a*b)。

    此外,printf 依赖整数提升来实现打印字符的 ASCII 值:printf("%d", a) 期望在调用 printf 时将 char-typed 参数提升为 int

    【讨论】:

    • 有人可以提示这个答案有什么问题吗(因为它被否决了)?
    • 我的也被否决了,没有评论。有些人从开车投票中获得乐趣。这样他们就可以表达自己的观点,而不必承担辩护的风险。
    猜你喜欢
    • 2017-07-10
    • 2017-06-03
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    相关资源
    最近更新 更多