7

Which of these are data type promotion and demotion :

char ch = 'C';
int i = 65;
float fl = 2.2;

ch = ch + 1;
i = fl + 2 * ch;
fl = 2.0 * ch + i;
ch = 5212205.17;

Am I correct if i say :

Promotion :

  • i = fl + 2 * ch;

  • fl = 2 * ch + i;

demotion :

  ch = 5211205.17;

not sure if

  ch = ch + 1;

Is also demotion.. please help :)

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Matt_p
  • 125
  • 2
  • 5

3 Answers3

12
char ch = 'C'; 

The literal 'C' is of type int and demoted to type char (conversion to the left operator during assignment).

float fl = 2.2;

The literal 2.2 is of type double and demoted to type float (conversion to the left operator during assignment).

ch = ch + 1;

The variable ch is of type char and promoted to type int (integer promotions).

The result of the addition ch + 1 is of type int and demoted to type char (conversion to the left operator during assignment).

i = fl + 2 * ch;

The variable ch is of type char and promoted to type int (integer promotions).

The result of 2 * ch is of type int and promoted to type float (balancing).

The result of fl + 2 * ch is of type float. The float is demoted to an int (conversion to the left operator during assignment). This is a dangerous conversion because of loss of precision and a good compiler should give a warning for attempting to store a float inside an int without an explicit cast.

fl = 2.0 * ch + i;

The variable ch is of type char and first promoted to type int (integer promotions) and then promoted to type double (balancing).

The result of 2.0 * ch is of type double.

The result of 2.0 * ch + i is of type double and demoted to type float (conversion to the left operator during assignment).

ch = 5212205.17;

The literal 5212205.17 is of type double and demoted to type char (conversion to the left operator during assignment). This is a dangerous conversion and possibly also undefined behavior, since the signedness of char is implementation-defined, and also the number cannot fit inside a char.

Attempting to store a signed floating point number inside a type that cannot represent it (such as an unsigned int) is undefined behavior, i.e. a severe bug.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Thanks for explaining each and every one ! I understood them better thanks to you :) – Matt_p Jan 23 '14 at 12:38
  • 1
    As you can hopefully tell from this, it is very important to understand what types your program is actually using. Constant literals have types as well as any variable, and they are subject to the same conversion rules. Which literal syntax you use determines the type, and thereby the outcome of the program. `1`, `1.0`, `1.0f`, `1U`, `1L`, `1UL`, `'1'`, `"1"` and so on, are all various different types. Programmers who don't understand this or don't understand implicit promotions _will_ write hundreds of hard-to-find bugs. It is not easy to learn, even veteran programmers struggle with this. – Lundin Jan 23 '14 at 12:50
  • Nice complete explanation. Idea to add: `long` to `float` promotion may lose precision. As in a 4-byte `long` 2147483647 to [binary32](http://en.wikipedia.org/wiki/Binary32) `float` which becomes 2147483648.0 – chux - Reinstate Monica Jan 23 '14 at 15:24
  • @chux Whether or not you lose precision does of course depend on the nature of the built-in types. What float format is use, how large is a long etc. Which in turn makes one realize that such code is unlikely to be portable, unless you are really, really careful. – Lundin Jan 23 '14 at 15:32
  • @lundin Thanks for the thorough answer. Could you also explain signed<->unsigned demotion/promotion ? – Alexey Polonsky Dec 07 '14 at 12:48
  • @AlexeyPolonsky Not sure what you mean, maybe [this](http://stackoverflow.com/questions/17312545/type-conversion-unsigned-to-signed-int-char)? – Lundin Dec 08 '14 at 07:10
  • @Lundin Thanks, actually I was hoping for something more detailed, like a set of rules that includes the fact that {int a=-5; a>>=8} would fill MSB of "a" with 1's, but {unsigned int a=-5; a>>=8} would fill MSB of "a" with zeros. – Alexey Polonsky Dec 08 '14 at 07:21
  • @AlexeyPolonsky Your particular example has nothing to do with type promotion. The shift operators follow specific rules. And there are actually no guarantees of what will happen when you right shift a negative integer: it is implementation-defined behavior. Performing shift operations on signed and/or negative integers is a bug/doesn't make any sense, in 99% of the cases. – Lundin Dec 08 '14 at 10:54
  • @Lundin Bingo ! Undefined behavior is a good answer. I just looked in C ISO2011 standard and it brings exactly this case as an example : "An example of implementation-defined behavior is the propagation of the high-order bit when a signed integer is shifted right." – Alexey Polonsky Dec 09 '14 at 10:19
  • @AlexeyPolonsky Please note that _right shift of a negative number is implementation-defined behavior_, it could perform arithmetic shift (fill up with the sign bit) or logical shift (fill up with zeroes) or something else. But _left shift of a negative number is undefined behavior_, you shift data into the sign bit and then anything can happen. – Lundin Dec 09 '14 at 13:50
  • Can someone help explain why `2 * ch` is promoted to type float (balancing)? Shouldn't `ch` be promoted to `int` then multiplied with `2`; the outcome of which is still `int`? – Andy J Mar 03 '17 at 04:04
  • @AndyJ Indeed, both operands `2` and `ch` are promoted to `int` if needed. The promotion of the result of `2 * ch` to `float` takes place when a float operand is involved here: `fl + 2 * ch`. The whole expression is equivalent to `i = (int) (fl + (float)(2 * (int)ch));`. See [the usual arithmetic conversions](https://msdn.microsoft.com/en-us/library/3t4w2bkb.aspx). – Lundin Mar 03 '17 at 07:34
  • Thanks Lundin. I understand a lot clearer now. But I'm a little discombobulated by your use of the word "Balanced". I googled it for the context of this topic and google yielded nothing. – Andy J Mar 05 '17 at 09:51
  • @AndyJ "Balancing" is an informal term for "the usual arithmetic conversions". Implicit type promotion is the general term. – Lundin Mar 06 '17 at 07:25
1

In ch = ch+1; Here 1 is an integer so ch is promoted to integer and add to 1 then result is demoted to character and stored in ch.

Chinna
  • 3,930
  • 4
  • 25
  • 55
0

I've never heard of such a concept as "data type demotion" in C programming.

"Promotion" is usually used to denote the fact of converting a "small" type to a bigger type which is native on the platform for which the program is compiled.

For instance, on an x86, gcc will promote an 8-bit char to a 32-bit integer, because the ALU of an x86 processor works on 32-bit words for integers.

To come back to your question, either it's about implicit type conversion, or we miss some context to be able to say which variable will be promoted.

Disclaimer : it looks like you may be preparing for an exam, in which case you should probably stick to your teacher's conventions. Maybe he's calling implicit conversion of an integer or a floating point type to a larger integer respectively floating point type a promotion, the truncation of the fractional part as a demotion, or an integer overflow as a demotion as well.

MikeySec
  • 81
  • 6
  • 2
    There is indeed a formal definition of "promotion" in the C standard, but no such formal definition of "demotion". The C standard does speak of type demotion in non-normative text however. What we informally call demotion, would formally be called _conversion during simple assignment_ or some such, it is specified in C11 6.5.16.1. – Lundin Jan 23 '14 at 12:43