Theo Niko
Theo Niko

Reputation: 27

Implicit conversion in c++ for between unsigned types of bit length ie uint8_t,uint16_t

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

Answers (1)

KamilCuk
KamilCuk

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 ) or B*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

Related Questions