1

What is the type of the result of a multiplication of two chars in C/C++?

unsigned char a = 70;
unsigned char b = 58;
cout << a*b << endl; // prints 4060, means no overflow
cout << (unsigned int)(unsigned char)(a*b) << endl; // prints 220, means overflow

I expect the result of multiplying two number of type T (e.g., char, short, int) becomes T. It seems it is int for char because sizeof(a*b) is 4.

I wrote a simple function to check the size of the result of the multiplication:

template<class T>
void print_sizeof_mult(){
  T a;
  T b;
  cout << sizeof(a*b) << endl;
}

print_sizeof_mult<char>(), print_sizeof_mult<short>(), and print_sizeof_mult<int>() are 4 and print_sizeof_mult<long>() is 8.

Are these result only for my particular compiler and machine architecture? Or is it documented somewhere that what type is the output of basic operations in C/C++?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
ebi
  • 501
  • 3
  • 12
  • 3
    The type of multiplying two `T`is `int` if all the possible values of `T` are in range for `int`. The C++ Standard documents the behaviour. C and C++ are different languages, in C your code would left-shift a variable called `cout` – M.M Apr 20 '17 at 22:13
  • @M.M: actually, in C the compiler would start complaining at `template<`. – Matteo Italia Apr 20 '17 at 22:18
  • 3
    See "integral promotion": http://en.cppreference.com/w/cpp/language/implicit_conversion#Integral_promotion – Daniel Waechter Apr 20 '17 at 22:19

1 Answers1

4

According to the C++ Standard (4.5 Integral promotions)

1 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.

and (5 Expressions)

10 Many 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:

....

  • Otherwise, the integral promotions (4.5) shall be performed on both operands.61 Then the following rules shall be applied to the promoted operands:

and at last (5.6 Multiplicative operators)

2 The operands of * and / shall have arithmetic or unscoped enumeration type; the operands of % shall have integral or unscoped enumeration type. The usual arithmetic conversions are performed on the operands and determine the type of the result.

Types char and short have conversion ranks that are less than the rank of the type int.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 1
    To remember these rules is useful to think at `char` and `short` as "storage types", i.e. smaller types that only come into play when you store your data in memory (and you want to save some); when performing operations they don't really exist, once the data is in the registers the arithmetic is done in the full registers size (which is what `int` originally was - a value corresponding to the machine register). – Matteo Italia Apr 20 '17 at 22:25