12

在 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

为什么?

4

7 回答 7

26

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

于 2013-10-19T21:21:57.320 回答
3

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

2)sizeof(<some char>)将始终为“1”。这就是“sizeof()”的意思——它永远不能是“1”之外的任何东西。

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

更多详情:

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

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

于 2013-10-19T21:20:49.803 回答
3

第 4.5 节 积分促销

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

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

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

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

否则,应在两个操作数上执行积分提升 (4.5)。59

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

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

于 2013-10-19T21:26:51.963 回答
3

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

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

于 2013-10-19T21:28:43.097 回答
3

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

关于如何解析以及如何读取操作数的更多详细信息:

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

于 2013-10-19T21:33:28.007 回答
2

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

于 2013-10-19T21:59:37.400 回答
1

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

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

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

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

于 2013-10-19T21:36:17.650 回答