I have a bit of C code, which goes exactly like this:
short int fun16(void){
short int a = 2;
short int b = 2;
return a+b;
}
Wh
When both operands are short
, they are implicitly promoted to int
in arithmetic operations.
GCC will only perform these implicit upscaling to int on operations which generate temporaries:
++i
i += 2
will not generate temporaries.
i = j + 1
will.
The following code:
std::cout << sizeof(i) << " "
<< sizeof(i + 1) << " "
<< sizeof(i + static_cast<unsigned short>(1)) << " "
<< sizeof(static_cast<unsigned short>(i) + static_cast<unsigned short>(1)) << " "
<< sizeof(++i) << " "
<< sizeof(i + 0x0F) << " "
<< sizeof(i += 1) << std::endl;
Will give the following output in either release or debug modes: 2 4 4 4 2 4 2
Indicating that while some things may suppress the warning, they don't actually stop the compiler upscaling to int. So to lose the warning, stop the generation of temporaries.
From The C Programming Language section 2.7 Type Conversion
long double
, convert the other to long double
.double
, convert the other to double
.float
, convert the other to float
.char
and short
to int
.long
, convert the other to long
.Quoting the standard (§6.3.1.1 ¶2):
The following may be used in an expression wherever an
int
orunsigned int
may be used:
- An object or expression with an integer type (other than
int
orunsigned int
) whose integer conversion rank is less than or equal to the rank ofint
andunsigned int
.- A bit-field of type
_Bool
,int
,signed int
, orunsigned int
.If an
int
can represent all values of the original type, the value is converted to anint
; otherwise, it is converted to anunsigned int
. These are called the integer promotions. All other types are unchanged by the integer promotions.
The -Wconversion flag warns about:
Warn for implicit conversions that may alter a value. This includes conversions between real and integer, like
abs (x)
whenx
isdouble
; conversions between signed and unsigned, likeunsigned ui = -1;
and conversions to smaller types, likesqrtf (M_PI)
. Do not warn for explicit casts likeabs ((int) x)
andui = (unsigned) -1
, or if the value is not changed by the conversion like inabs (2.0)
. Warnings about conversions between signed and unsigned integers can be disabled by using-Wno-sign-conversion
.
When you do arithmetic computations, the operands are subject to "the usual arithmetic conversions" (a superset of the "integer promotions" quoted in Acme's answer—he beat me to this but I'll go ahead and post anyway :-) ). These widen short int
to plain int
, so:
a + b
computes the same result as:
((int) a) + ((int) b)
The return
statement must then narrow this int
to a short int
, and this is where gcc produces the warning.
If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.
Refer the following post: Why must a short be converted to an int before arithmetic operations in C and C++?