0

I understand the difference between ++i and i++. I think this case is different,

I wrote this code,

u_int8_t a = 255;
main (){
   
    printf("Num is %d\n", ++a ) ;
   

}

Which outputs

Num is 0

But this code,

u_int8_t a = 255; 
main (){
   
    printf("Num is %d\n", a+1 ) ;
   

}

Which outputs,

Num is 256

What is the reason for different outputs?

  • the 1 is regarded as an int. The int operator+ implicitly casts your u_int8_t to an int therefore you get the print of an int and not of your u_int8_t. See the comment above. – Taron May 25 '21 at 09:52
  • @Lundin You have 'suggested' a duplicate but not closed this question (as you presumably can, with your C hammer). Is that because you're not sure that it's a duplicate? – Adrian Mole May 25 '21 at 09:52
  • 3
    @AdrianMole It's because I'm the author of the proposed dupe and therefore partial. I think it is questionable to close questions with your own posts as the target. – Lundin May 25 '21 at 09:53
  • @Lundin OK - fair comment. – Adrian Mole May 25 '21 at 09:54
  • @Lundin It answers my question, thank you – Jonathan Wick May 25 '21 at 10:17

2 Answers2

1

The expression ++a increments a in the context of its type (8-bit unsigned) so wraps around to zero.

The expression a + 1 adds the 8-bit unsigned a to the literal 1 (which is an int) and, when you do that with disparate types, the smaller of them is usually "upgraded" to the other before adding. Hence you're then adding the two int values, 255 and 1, with no wrapping.

This is known in C as the "usual arithmetic conversions" and the section of the standard that deals with it, C11 6.3.1.8, begins:

Many operators that expect operands of arithmetic type cause conversions and yield result types in a similar way. The purpose is to determine a common real type for the operands and result.

After going through some floating point types, the following dictates how integral types are handled:

Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands:

  • If both operands have the same type, then no further conversion is needed.
  • Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
  • Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.
  • Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.
  • Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

You may think that it's the fourth bullet point that comes into play here but, in actual fact, it's the preamble combined with the first bullet point. The "integer promotions", detailed in C11 6.3.1.1, will actually take integral types of lesser or equal rank to int and turn them into an int (assuming that can represent all values of the original type, otherwise it makes it unsigned int).


The other difference, of course, is that the first one modifies a but the second one does not.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
0

You can squeeze the conversion between the variable and the unary prefix ++ operator:

printf("Num is %d\n", ++(int){a} );   // 256

The compound literal is needed; with only a cast there is a ++ needs lvalue error.


++a evaluates first to 0 and then gets converted . In a + 1 a gets converted first (and is not increased).