'Sum of two chars in C/C++
In C/C++ when I want to find sum of two chars - I get result in int.
For example:
#include <stdio.h>
int main(){
char a = 'a', b = 'b';
printf("%d + %d = %d\n", sizeof(a), sizeof(b), sizeof(a + b));
return 0;
}
Prints
1 + 1 = 4
Why?
Solution 1:[1]
Because although a
and b
are each of type char
, the expression a + b
is of type int
. Anytime you do math with char types, they are converted to int before doing the actual calculations.
Solution 2:[2]
1) This just prints out the text string "something + something else": you're not actually adding anything: printf("%d + %d = %d\n",..)
2) sizeof(<some char>)
will always be "1". That's what "sizeof()" means - it can never be anything besides "1".
3) Yes, adding type "char" (which is an integer subtype) will give an integral result.
For further details:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
The type char, the signed and unsigned integer types, and the enumerated types are collectively called integer types. The integer and real floating types are collectively called real types.
Solution 3:[3]
Because, if not promoted, the result can overflow.
A single byte char cannot hold value greater than 255 (unsigned) or +127 (signed). When you sum two instances, there is always the possibility of overflow i.e. result exceeding 255. This means it cannot be stored in a single byte. Hence int is used which cannot over flow max sum of two chars or bytes.
Solution 4:[4]
Looking at the ANSI C specification, here is how additive expressions are parsed.
More elaboration on how this is parsed and how operands are read:
The integral operand of an additive operator involving a pointer and an integer is specified to be a TypeIs_unsigned_long. Any integral type can be converted to TypeIs_unsigned_long by means of implicit conversions, so this specification is equivalent to that of the standard. The main reason for using TypeIs_unsigned_long is that OIL does not permit sets as operand specifications within a class definition, but a secondary reason is that this approach reduces the total number of operators in the compiler's database.
Solution 5:[5]
Section 4.5 Integral promotions
A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank (4.13) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.
The conversion is mandated by the standard in what is called "The usual arithmetic conversions" Clause 5 [expr] point 10:
Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similarMany binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows: way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:
Unless for a few select types. long double, double
and float
Otherwise, the integral promotions (4.5) shall be performed on both operands.59
The (char)+(char) results in an int.
Also note that a char+char is tricky. The char can be signed or unsigned depending on implementation; so the result might easily overflow for normal values which is likely why it is not included in the standard as an exception.
Solution 6:[6]
The reason for this promotion is historical: when C was invented, 40+ years ago, processors did math on a single integral type; you could store smaller types, but there was no byte-level arithmetic. So the promotion rule reflects reality at the time: types smaller than the processor's integer type would be promoted by the hardware to that integer type. Sure, you could do the math in software (which is how long
was often implemented), but that would have been much slower (as long
often was).
Solution 7:[7]
This is how C and C++ work: before doing anything on variables of type char
, the compiler converts them to int
first. This is called integer promotion. Note: anything is defined by the C and C++ Standards; it doesn't include sizeof
but includes most of other operations (I cannot remember any exceptions besides the sizeof
one).
As to the reason for this maybe surprising behavior - this is probably a decision taken in ancient times, resulting in modern C and C++ behaving in that way since then, for compatibility.
People often had large arrays of char
s, which were not really characters, but small numbers. When doing arithmetic with these, it was natural to convert each number to int
automatically and doing arithmetic on these, because int
is the type for which arithmetic works the fastest. There is also the pleasant side-effect that overflow is much less likely to happen when promotion is in effect (consider a*b
when a
and b
are of char
type).
In addition, printf
relies on integer promotion to implement printing ASCII values for characters: printf("%d", a)
expects the char
-typed parameter to be promoted to int
when printf
is called.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Lee Daniel Crocker |
Solution 2 | |
Solution 3 | fkl |
Solution 4 | Jens |
Solution 5 | |
Solution 6 | |
Solution 7 | anatolyg |