Reputation: 27
I would like to know how to implicit casting works in case of expressions between unsigned int of various bits ie uint8_t,uint16_t etc and ways to avoid it explicitly. For this reason i sumarrized the following cases:
uint8_t A;
uint8_t B;
uint16_t C;
C= A+B; (uint8_t + uint8_t )
C= A-B; (uint8_t + uint8_t )
C= A*B; (uint8_t + uint8_t )
C= A/B; (uint8_t + uint8_t )
Explicit declaration would be C= static_cast<uint16_t>A+B; or C= static_cast<uint16_t>(A+B);.Is this correct? Is there any difference between C= static_cast<uint16_t>A+B; or C= static_cast<uint16_t>(A+B)?
C= A+1U;(uint8_t + uint8_t )
C= A-1U;(uint8_t - uint8_t )
C= 1U*B;(uint8_t * uint8_t )
C= 1U/B;(uint8_t / uint8_t )
Explicit casting would be C= static_cast<uint16_t>A+1U; or C= static_cast<uint16_t>(A+1U); C= static_cast<uint16_t>1UB; or C= static_cast<uint16_t>(1UB);.Is that correct Is there any difference between those lines?
C= 1U/(A-1U); (unsigned int / (uint8_t -(unsigned int))
C= (C-(A/B))/B; (uint8_t -(uint8_t /(unsigned int))/(uint8_t)
How should static_cast look in this case? Only the first variable (1U or C) would define for the rest C= static_cast<uint8_t >(1U)/(A-1U);
sizeof(A) returns size_t
C=abs(-1*A) returns int in case of int parmaters
Explicit casting would be C= static_cast<uint16_t>sizeof(A) and C= static_cast<uint16_t>abs(-1*A). Is that correct? What about C= static_cast<uint16_t>abs(-1)*A)?
uint16_t sum(uint16_t C1,uint16_t C2);
C=sum(A,B-1U/2U);
C=sum(A,1U/2U-B);
Explicit casting would be C= sum(static_cast<uint16_t>(A),static_cast<uint16_t>(B-1U/2U)). Is that correct?
I saw in Opencv a similar to static_cast function called saturate_cast. Would it be a beter solution in any of the above cases?
Upvotes: -1
Views: 1448
Reputation: 142005
How implicit casting in case of uint8_t addition,substraction,multiplication,division would work?
uint8_t
has conversion rank lesser then type int
and type int
can always hols the entire value range of uint8_t
, UINT8_MAX
is 255 and int
has at least 16 bits. uint8_t
will be promoted to int
by integral promotion prior to operator. cppreference integral promotion fundamental types cstdint
Explicit declaration would be C= static_cast<uint16_t>A+B; or C= static_cast<uint16_t>(A+B);. Is this correct?
No. These are not examples of declarations, type specifier is missing. They are using operator=
to assign a value to object C
. An "explicit declaration" would be a declaration that uses the auto
keyword. cppreference declaration
Is there any difference between C= static_cast<uint16_t>A+B; or C= static_cast<uint16_t>(A+B)?
Yes, on architecture where int
can't hold all range of values of uint16_t
. In that particular case, the first expression first promotes the operands of +
operator to unsigned int
, while the second one carries the operation using int
types. The second expression is the same as C = A + B
, because C
has type uint16_t
. Except that particular case, on architectures where int
can hold all range of values of uint16_t
, both operands will be promoted to int
. C= static_cast<uint16_t>(A+B)
is the same as C = A + B
.
How implicit casting in case of expressions of unsigned int(with U literal)and uint8_t would work?
First both operands undergo integral promotions. unsigned int
stays and uint8_t
is promoted to int
. Then the operands undergo integral conversions. Because one of the operands is unsigned
and both operands have the same conversion rank, the signed operand is converted to unsigned type, ie. int
is converted to unsigned int
. arithmetic operators and arithmetic conversions
Is there also a difference between the order that it matters ie
1U*B;(unsined int * uint8_t )
orB*1U;(uint8_t * uint8_t )
No, the order of operands does not matter.
Explicit casting would be C= static_cast<uint16_t>A+1U; or C= static_cast<uint16_t>(A+1U); C= static_cast<uint16_t>1UB; or C= static_cast<uint16_t>(1UB);. Is that correct Is there any difference between those lines?
static_cast<uint16_t>1UB
is a syntax error. C = static_cast<declatype(C)>(expr)
is always equal to C = expr
.
How the implicit casting in case of expressions would work. Is the normal order take into account?
I do not understand what is a "normal order". The operands and expression are evaluated according to their precedences.
What would it be the final type of the expression?
C= 1U/(A-1U); (unsigned int / (uint8_t -(unsigned int))
The expression on the right side of operator=
is an rvalue of unsigned int
type.
C= (C-(A/B))/B; (uint8_t -(uint8_t /(unsigned int))/(uint8_t)
The expression on the right side of operator=
is an rvalue of unsigned int
type.
How should static_cast look in this case?
Like anywhere else static_cast<type>(expr)
Only the first variable (1U or C) would define for the rest C= static_cast<uint8_t >(1U)/(A-1U);
Each operator evaluates it's operands separately, one or two expressions at a time. The order of evaluations (and thus promotions) is ordered according to precedence of operators. order of evaluation and precedence and associativity
How the implicit casting in case of standard functions would work?
Like with any other type according to the rules of integer promotions. size_t
is just an implementation defined unsigned integer type.
Explicit casting would be C= static_cast<uint16_t>sizeof(A) and C= static_cast<uint16_t>abs(-1*A). Is that correct?
Both expression are syntax error. It's static_cast<type> ( expression )
. Braces are mandatory. For answer see above - doing C = static_cast<decltype(C)>(expr)
is just equal to C = expr
.
What about C= static_cast<uint16_t>abs(-1)*A)?
What about it?
How the implicit casting in case of function parameters would work.
When arguments are not part of elipsis in a variadic function call then the arguments are converted to the argument type.
Explicit casting would be C= sum(static_cast<uint16_t>(A),static_cast<uint16_t>(B-1U/2U)). Is that correct?
Yes, but what for? They will be converted to uint16_t
anyway.
I saw in Opencv a similar to static_cast function called
saturate_cast
. Would it be a beter solution in any of the above cases?
"Better" is opinion based and vague. It depends on what you want to achieve. The saturate_cast
is a simple template that specifically handles types with range grater then destination range. In such cases the argument is converted to the maximum/minimum of that type.
For further research,. the draft of c++ standard is available online.
Upvotes: 0