C / C ++中两个字符的总和

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

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

打印

 1 + 1 = 4 

为什么?

因为虽然ab都是char类型,但表达式a + b的类型为int 。 无论何时使用char类型进行数学运算,在进行实际计算之前都会将它们转换为int。

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

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

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

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

2) sizeof()将始终为“1”。 这就是“sizeof()”的意思 – 除了 “1” 之外它永远不会是任何东西。

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

有关详细信息:

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

char类型,有符号和无符号整数类型以及枚举类型统称为整数类型。 整数和实数浮点类型统称为实数类型。

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

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

第4.5节整体促销

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

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

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

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

否则,应在两个操作数上执行整数促销(4.5)

(char)+(char)导致int。

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

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

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

人们经常有大量的字符串,这些字符不是真正的字符,而是数字很少。 在对这些进行算术运算时,很自然地将每个数字自动转换为int并对这些数字进行算术运算,因为int是算术运算速度最快的类型。 还有一个令人愉快的副作用,即当促销生效时,溢出的可能性更小(当abchar类型时,考虑a*b )。

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

这次推广的原因是历史性的:当C发明时,40多年前,处理器在一个整体类型上进行数学运算; 你可以存储较小的类型,但没有字节级算术。 因此,促销规则反映了当时的现实:小于处理器整数类型的类型将由硬件提升为该整数类型。 当然,你可以在软件中进行数学计算(通常实现的long ),但这会慢得多(通常很long )。