-1

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:

  • How implicit casting in case of uint8_t addition,substraction,multiplication,division would work?

    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)?

  • How implicit casting in case of expressions of unsigned int(with U literal)and uint8_t would work? Is there also a difference between the order that it matters ie 1UB;(unsined int * uint8_t ) or B1U;(uint8_t * uint8_t )

    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?

  • How the implicit casting in case of expressions would work.Is the normal order take into account? What would it be the final type of the expression?

    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);

  • How the implicit casting in case of standard functions would work

    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)?

  • How the implicit casting in case of function parameters would work.

    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?

Theo Niko
  • 27
  • 5
  • What is your question? – Cortex0101 Jun 27 '20 at 10:54
  • `The way to avoid` to avoid what? `The correct approach` Please define "correct". – KamilCuk Jun 27 '20 at 10:56
  • @Cortex: Mainly i need to know how implicit casting order in an expression is perfomed. For example C= 1U/(A-1U); (unsigned int / (uint8_t -(unsigned int)) C= (C-(A/B))/B; (uint8_t -(uint8_t /(unsigned int))/(uint8_t) what implicit type would it be returned for the above expressions on the right – Theo Niko Jun 27 '20 at 11:05
  • @KamilCuk: I changed the description to be more understandable. Please see my comment above as bried summary of this question. – Theo Niko Jun 27 '20 at 11:09
  • I think a good book and research would help you more then stackoverflow. – KamilCuk Jun 27 '20 at 11:32
  • For example: uint8_t A; uint8_t B; uint16_t C; C= 1U/(A-1U); The left expressions type will end up to uint8_t since this is the bigger type in(unsigned int / (uint8_t -(unsigned int)) and this uint8_t will be implicitly casted to uint16_t. In other words, the final type of an expressions would end up be the biggest type on the expression if there are uint8_t and uint32_t it will be uint32_t . Is my assumption correct? – Theo Niko Jun 27 '20 at 11:36
  • No, your assumption is wrong. – KamilCuk Jun 27 '20 at 11:44
  • Ok, so what would be the final type of the expression would be? – Theo Niko Jun 27 '20 at 11:49
  • Try not to guess programming. Instead research the actual rules. It's not magic, every corner case is exactly, explicitly and as clearly as possible described in the standard – KamilCuk Jun 27 '20 at 12:06
  • There is no such thing as an implicit cast. The term you're looking for is **implicit conversion**. A cast is something you write in your source code (hence, always explicit) to tell the compiler to do a conversion. – Pete Becker Jun 27 '20 at 12:46

1 Answers1

0

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.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111