Integral promotion. 
Author Message
 Integral promotion.



:
:>Excerpts from the standard:
:>
:>*  From 6.3.16.1/3.3.16.1:
:>#  In "simple assignment" (=), the value of the right operand is
:>#  converted to the type of the left operand ...
:>
:>*  From 6.2.1.2/3.2.1.2:
:>#  When a value with integral type is demoted to a signed integer with
:>#  smaller size ... if the value cannot be represented the result is
:>#  implementation-defined.                             ^^^^^^^^^^^^^
:>   ^^^^^^^^^^^^^^^^^^^^^^
:>Hence implementation-defined behavior occurs.
:
:Thus, the implementation has to say exactly how it handles this.
:There is still some question as to whether the implementation can
:define it as an overflow resulting in program termination, is there
:not?

This is open to debate.  According to the standard, the result of the
conversion is implementation-defined, not the behaviour of the program.

Dan
--
Dan Pop
CERN, CN Division

Mail:  CERN - PPE, Bat. 31 R-004, CH-1211 Geneve 23, Switzerland



Wed, 05 Aug 1998 03:00:00 GMT  
 Integral promotion.

Quote:


>>> Thus even in ANSI C, if this function is called this way:
>>>extern short p, q, r, test(short,short);
>>>r = test(p,q);
>>> the values from p and q are still converted from short to int and back
>>> to short.  

>>I find nothing in the Standard that states that the arguments undergo
>>integral promotions before being assigned to the function parameters.
>This is in 6.2.1.1/3.2.1.1, the passage which defines the integral
>promotions.  It states that the promotions apply
>#  in an expression wherever an int or unsigned int may be used.

It does not.  6.2/3.2 begins with the sentence:  "Several operators
convert values from one type to another automatically."  The entire
section proceeds to describe what kinds of conversions occur in which
kinds of contexts, all within the context of which operators convert
values automatically.  The entire section is irrelevant to other
contexts, such as those in which operators do not convert values
automatically (e.g. postfix ++, e.g. function call, e.g. sizeof,
even e.g. assignment when the left and right sides have the same type).

Part of the definition of the binary + operator is to perform the
integral promotions on its operands.  There is stuff like this all
over the chapter on expressions.  If all this stuff were unnecessary,
they might not have repeated it 20 times, or it might have been caught
and submitted as a defect report many years ago.

You miscorrected Chris Torek and you made him believe you.  You
miscorrected Thad Smith and me, but we aren't falling for it.
--
 <<  If this were the company's opinion, I would not be allowed to post it.  >>
"I paid money for this car, I pay taxes for vehicle registration and a driver's
license, so I can drive in any lane I want, and no innocent victim gets to call
the cops just 'cause the lane's not goin' the same direction as me" - J Spammer



Sun, 09 Aug 1998 03:00:00 GMT  
 Integral promotion.

Quote:

>> > short test(short x1, short x2) {
>> >  short result;
>> >  result = x1 + x2;

>> The addition operator "+" converts your short operands to ints.

>No, just using their values does that.  The operator + never sees
>operands narrower than int.  In the statement
>    x1;
>the short is converted to int before being discarded.

Okay, I'm confused.  Let just say the above is true.  Then the expression
"x1 + x2" has type int because x1 and x2 were converted to int before
being passed to the + operator.

So what if sizeof(short) == sizeof(int)?  Assuming both x1 and x2 are
non-negative, would "x1 + x2" be unsigned int if it wouldn't fit in an
int?  In short, would there be undefined/implementation defined behaviour
if "result" is unsigned int?  How about long?


Witty .sig under construction.



Sun, 09 Aug 1998 03:00:00 GMT  
 Integral promotion.

Quote:
(Lawrence Kirby) writes:

<snip>

    > > > short test(short x1, short x2) {
    > > >  short result;
    > > >  result = x1 + x2;
    > >
    > > The addition operator "+" converts your short operands to ints.
    >
    > No, just using their values does that.  The operator + never sees
    > operands narrower than int.  In the statement
    >         x1;
    > the short is converted to int before being discarded.

   This does however beg a question regarding the standard. Take the
   >> or << operators. In 6.3.7 we have:

   "Constraints

        Each of the operands shall have integral type

    Semantics

        The integral promotions are performed on each of the operands..."

   If the operator never sees operands narrower than int then this sentence
   is pointless.


states that integral promotions take place whenever an int is
allowed. I still believe it states that, but erroneously ... after
`char x', sizeof x better be sizeof(char) and not necessarily
sizeof(int), even though an int is allowed as an operand of sizeof.

I think the footnote needs to be brought into the body of the
standard. I also think that either enums should be prohibited from
being (unsigned) long, or they should be treated somewhat differently
in this clause.

In any case, currently, whether an integral promotion takes place
before the value is discarded or not has little bearing on the
behaviour of the program. The topic is quite okay in comp.std.c:
there one is trying to find whether the standard is inconsistent and
it is important to figure out how any change will interact with the
rest of the standard. In c.l.c.m, it is probably not off-topic, but
not very interesting. I have accordingly set follow-up to comp.std.c;
if it survives moderator's software and it is not appropriate, please
change it back.

Cheers
Tanmoy
--

Tanmoy Bhattacharya O:T-8(MS B285)LANL,NM87545 H:#9,3000,Trinity Drive,NM87544
Others see <gopher://yaleinfo.yale.edu:7700/00/Internet-People/internet-mail>,
<http://alpha.acast.nova.edu/cgi-bin/inmgq.pl>or<ftp://csd4.csd.uwm.edu/pub/
internetwork-mail-guide>. -- <http://nqcd.lanl.gov/people/tanmoy/tanmoy.html>
fax: 1 (505) 665 3003   voice: 1 (505) 665 4733    [ Home: 1 (505) 662 5596 ]



Sun, 09 Aug 1998 03:00:00 GMT  
 Integral promotion.

 > > > short test(short x1, short x2) {
 > > >  short result;
 > > >  result = x1 + x2;
 > >
 > > The addition operator "+" converts your short operands to ints.
 >
 > No, just using their values does that.  The operator + never sees
 > operands narrower than int.  In the statement
 >         x1;
 > the short is converted to int before being discarded.

This does however beg a question regarding the standard. Take the

Quote:
>> or << operators. In 6.3.7 we have:

"Constraints

     Each of the operands shall have integral type

 Semantics

     The integral promotions are performed on each of the operands..."

If the operator never sees operands narrower than int then this sentence
is pointless.

--
-----------------------------------------


-----------------------------------------



Sun, 09 Aug 1998 03:00:00 GMT  
 Integral promotion.


Quote:
> >> The addition operator "+" converts your short operands to ints.

> >No, just using their values does that ...
> Okay, I'm confused.  Let just say the above is true.  Then the expression
> "x1 + x2" has type int because x1 and x2 were converted to int before
> being passed to the + operator.

I admit that I am confused too. So in this case the compiler should issue a
warning for { short x = 0; x++; } since "x++" equals "x = x + 1" and both
"x" and "1" are promoted to integers, and there could therefore be a
potential loss of precision because "sizeof(int) > sizeof(short)", but no
precision could have been lost if int and short had been the same (small)
size ?? <phew>

This again implies that the ++ operator should be avoided on short
since it is destined to cause havoc and confusion ... Which in turn is
not the way C is written ... (Ehrm  :)

[testing] _I can't even cast my way out of this!?_

problem_with(short i){
  assert(sizeof (int) > sizeof (short));
  return i++;    /* Warning: Precision may be lost */

Quote:
}

I never saw this in any textbook :-)

// Jens M Andreasen



Sun, 09 Aug 1998 03:00:00 GMT  
 Integral promotion.

Quote:
(S. Lee) writes:

<snip>

   >> > short test(short x1, short x2) {
   >> >  short result;
   >> >  result = x1 + x2;
   >>
   >> The addition operator "+" converts your short operands to ints.
   >
   >No, just using their values does that.  The operator + never sees
   >operands narrower than int.  In the statement
   > x1;
   >the short is converted to int before being discarded.

   Okay, I'm confused.  Let just say the above is true.  Then the expression
   "x1 + x2" has type int because x1 and x2 were converted to int before
   being passed to the + operator.

   So what if sizeof(short) == sizeof(int)?  Assuming both x1 and x2 are
   non-negative, would "x1 + x2" be unsigned int if it wouldn't fit in an
   int?  In short, would there be undefined/implementation defined behaviour
   if "result" is unsigned int?  How about long?

Why would x1+x2 become an unsigned int? It is x1 and x2 that are
converted to ints: integral promotions occur on the operands, not on
the result! When you add int's you get an int: and if the result does
not fit, you are in trouble!

Furthermore, what x1 is promoted to does not depend on the _value_ of
x1, but the _type_ of x1. If all values that the type can hold can fit
into an int, it becomes an int: otherwise it becomes an unsigned
int. Thus if x is unsigned short with value 2, USHRT_MAX is greater than
INT_MAX, x is promoted to unsigned int and not to an int, because
there exists some unsigned short value which does not fit into an int,
even though the particular value 2 does. This is a general feature of
C: the type of an expression does not depend on any _evaluation_
(except for evaluation of integral constants, possible at compile
time, to find array dimensions and the like).

The case you are talking of is even simpler. int must be able to hold
all values that a short holds. So, if x1 and x2 are short, they are
promoted to int, and x1+x2 is therefore also an int: and if the result
does not fit, the compiler won't do anything to save you.

Cheers
Tanmoy
--

Tanmoy Bhattacharya O:T-8(MS B285)LANL,NM87545 H:#9,3000,Trinity Drive,NM87544
Others see <gopher://yaleinfo.yale.edu:7700/00/Internet-People/internet-mail>,
<http://alpha.acast.nova.edu/cgi-bin/inmgq.pl>or<ftp://csd4.csd.uwm.edu/pub/
internetwork-mail-guide>. -- <http://nqcd.lanl.gov/people/tanmoy/tanmoy.html>
fax: 1 (505) 665 3003   voice: 1 (505) 665 4733    [ Home: 1 (505) 662 5596 ]



Sun, 09 Aug 1998 03:00:00 GMT  
 Integral promotion.

 > > > short test(short x1, short x2) {
 > > >  short result;
 > > >  result = x1 + x2;
 > >
 > > The addition operator "+" converts your short operands to ints.
 >
 > No, just using their values does that.  The operator + never sees
 > operands narrower than int.  In the statement
 >         x1;
 > the short is converted to int before being discarded.

This does however beg a question regarding the standard. Take the

Quote:
>> or << operators. In 6.3.7 we have:

"Constraints

     Each of the operands shall have integral type

 Semantics

     The integral promotions are performed on each of the operands..."

If the operator never sees operands narrower than int then this sentence
is pointless.

--
-----------------------------------------


-----------------------------------------



Sun, 09 Aug 1998 03:00:00 GMT  
 Integral promotion.

:
:
:> > Thus even in ANSI C, if this function is called this way:
:> >
:> >     extern short p, q, r, test(short,short);
:> >     r = test(p,q);
:> >
:> > the values from p and q are still converted from short to int and back
:> > to short.  
:

:> I find nothing in the Standard that states that the arguments undergo
:> integral promotions before being assigned to the function parameters.
:
:This is in 6.2.1.1/3.2.1.1, the passage which defines the integral
:promotions.  It states that the promotions apply
:
:#  in an expression wherever an int or unsigned int may be used.
:
:Since the call test(1,2) is permissible, this means that p and q must
:be promoted to int.  As noted in my previous posting, they are then
:converted right back to short within the caller (since a prototype
:was used), and the compiler can easily optimize this out.
:

This is a somewhat perverse reading of the standard. It does not require
pointless promotions followed by conversions back to the original type. In
particular, there is a footnote to this section that says

        The integral promotions are applied only as part of the usual
        arithmetic conversions, to certain argument expressions, to the
        operands of the unary +, -, and ~ operators, and to both operands
        of the shift operators, AS SPECIFIED BY THEIR RESPECTIVE SECTIONS.
        [emphasis added]

That is, this section does not tell you what must be done every time you
encounter something that could be promoted to int. It tells you what the term
"integral promotions" means when it is used in other sections of the working
paper. In particular, it tells you what "integral promotions" means in the
context of the "usual arithmetic conversions", which is where it is most often
encountered.

:Another example of this sort of thing is an assignment expression like
:p=q, where p and q are short.  q is promoted to int, then demoted back
:to short; since the value cannot change, the compiler optimizes out the
:conversions.  If you write p=(short)q, then the same reason applies
:to each of the expressions q and (short)q, and you end up with *two*
:round-trip conversions which should be optimized out.

No. The description of the semantics of the assignment operator does not
mention integral promotions. Compare that with the description of the addition
operator, which says, in part, "If both operands have arithmetic type, the
usual arithmetic conversions are performed on them."



Sun, 09 Aug 1998 03:00:00 GMT  
 Integral promotion.

Quote:


>(S. Lee) writes:

[lossy compression]

Quote:
>Furthermore, what x1 is promoted to does not depend on the _value_ of
>x1, but the _type_ of x1. If all values that the type can hold can fit
>into an int, it becomes an int: otherwise it becomes an unsigned
>int.

Yes, I was confused by this statement.  I thought it referred to the
value.

Your message clears it up for me.  Thanks.

Rgds

Witty .sig under construction.



Sun, 09 Aug 1998 03:00:00 GMT  
 Integral promotion.
[comp.std.c removed from the newsgroups list; I don't think they care]



: > >> The addition operator "+" converts your short operands to ints.
: > >
: > >No, just using their values does that ...

: > Okay, I'm confused.  Let just say the above is true.  Then the expression
: > "x1 + x2" has type int because x1 and x2 were converted to int before
: > being passed to the + operator.

: I admit that I am confused too. So in this case the compiler should issue a
: warning for { short x = 0; x++; } since "x++" equals "x = x + 1" and both
: "x" and "1" are promoted to integers, and there could therefore be a
: potential loss of precision because "sizeof(int) > sizeof(short)", but no
: precision could have been lost if int and short had been the same (small)
: size ?? <phew>

First of all, x++ does not "equal" x = x + 1, although that is a
convenient fiction.  For another example of where this conversion
before binary operators can cause problems, consider code like:

unsigned short x = ~0;

if (!(~x)) puts("Suprise!  We never get here.");

The reason, of course, is that in the process of being widened from
short to int, the value 'x' which is originally all 1's picks up
some zeros, so ~x is no longer zero.

---------------------------------------------------------------------------
Tim Hollebeek         | Disclaimer :=> Everything above is a true statement,
Electron Psychologist |                for sufficiently false values of true.

----------------------| http://wfn-shop.princeton.edu/~tim (NEW! IMPROVED!)



Sun, 09 Aug 1998 03:00:00 GMT  
 Integral promotion.


Quote:
>I admit that I am confused too. So in this case the compiler should issue a
>warning for { short x = 0; x++; } since "x++" equals "x = x + 1" and both
>"x" and "1" are promoted to integers, and there could therefore be a
>potential loss of precision because "sizeof(int) > sizeof(short)", but no
>precision could have been lost if int and short had been the same (small)
>size ?? <phew>

x++ is not the same as "x = x + 1".  "++x" nearly is.

-s
--

C/Unix wizard -- C/Unix questions? Send mail for help.  No, really!
{*filter*} the communications decency act.  Goddamned government.  [literally.]
The *other* C FAQ - http://www.*-*-*.com/ ~seebs/c/c-iaq.txt



Sun, 09 Aug 1998 03:00:00 GMT  
 Integral promotion.

Quote:

>First of all, x++ does not "equal" x = x + 1, although that is a
>convenient fiction.  For another example of where this conversion
>before binary operators can cause problems, consider code like:

>unsigned short x = ~0;

>if (!(~x)) puts("Suprise!  We never get here.");

>The reason, of course, is that in the process of being widened from
>short to int, the value 'x' which is originally all 1's picks up
>some zeros, so ~x is no longer zero.

15 Nekomi [~] 0 % cat t.c

#include <stdio.h>

int main(void)
{
    unsigned short x = ~0;

    if (!(~x)) puts("Suprise!  We never get here.");

    return 0;

Quote:
}

16 Nekomi [~] 0 % gcc -W -Wall t.c -o t

t.c: In function `main':
t.c:7: warning: comparison of promoted ~unsigned with constant

17 Nekomi [~] 0 % ./t
18 Nekomi [~] 0 %

Wow.  I didn't even know gcc has such a warning.  And indeed it doesn't
work.  Guess you learn something new each day.


Witty .sig under construction.



Mon, 10 Aug 1998 03:00:00 GMT  
 Integral promotion.
Re: short = short + short causing a warning.

This is all getting off the track.  Since only a warning is generated this
has very little to do with the standard.  I think the point is why does

short = short + short;

generate a warning whereas

int = int + int;

does not.  Both these statements are as prone to overflow as each other
(although in the first case it may not happen until the int resulting
from the addition is moved into the short if sizeof(int) > sizeof(short).

The warning is even sillier since on the implementation mentioned
ints and shorts are the same.



Mon, 10 Aug 1998 03:00:00 GMT  
 Integral promotion.

Quote:

>>>> Thus even in ANSI C, if this function is called this way:
>>>>        extern short p, q, r, test(short,short);
>>>>        r = test(p,q);
>>>> the values from p and q are still converted from short to int and back
>>>> to short.  [but in the caller, where this is trivially optimizable-out]

And when challenged, justified this by citing:

Quote:
>> ... 6.2.1.1/3.2.1.1, the passage which defines the integral
>> promotions.  It states that the promotions apply
>> #  in an expression wherever an int or unsigned int may be used.

This interpretation was objected to in the Referenced article by

| there is a footnote to this section that says
|
|       The integral promotions are applied only as part of the usual
|       arithmetic conversions, to certain argument expressions, to the
|       operands of the unary +, -, and ~ operators, and to both operands
|       of the shift operators, AS SPECIFIED BY THEIR RESPECTIVE SECTIONS.
|       [emphasis added]
|
| That is, this section does not tell you what must be done every time
| you encounter something that could be promoted to int.  It tells you
| what the term "integral promotions" means when it is used in other
| sections...  In particular, it tells you what "integral promotions"
| means in the context of the "usual arithmetic conversions", which is
| where it is most often encountered.



Quote:
> 6.2/3.2 begins with the sentence:  "Several operators convert values
> from one type to another automatically." ...  The entire section is
> irrelevant to other contexts, such as those in which operators do not
> convert values automatically...

It is clear both from the footnote and the abundant references to
integral promotions throughout 6.3.*/3.3.* that Pete and Norman have
correctly interpreted the intent of the standard, so I was wrong to
that intent.  In my defense, I was fooled by the very explicit statement
that I cited in 6.2.1.1/3.2.1.1 -- and by similar language in K&R1, mem-
orized long ago -- into not looking for material that might contradict it.

And in fact, as to what the standard actually requires, I maintain that
I was right and Norman and Pete wrong.  But it doesn't matter anyway,
because both interpretations always yield the same result!

First off, footnotes are not part of the standard, so if they contradict
the text of the standard, they are supposed to be ignored.  Preferably,
in that case someone files a Defect Report and eventually the conflict
is resolved -- as Tanmoy Bhattacharya said in yet another branch of
the thread, moving the footnote into the main text would make sense.

Second, 6.2/3.2, in common with other sections of similar type, is best
read as a synopsis of the primary purpose of the sections that follow.
It is not stated as explicitly taking precedence over other material
such as 6.2.1.1/3.2.1.1; contrast this with the way that 7.1.7/4.1.6
does explicitly take precedence over the sections following it.

Also contrast 6.2.1.1/3.2.1.1, which defines the integral promotions
and states where they apply, with 6.2.1.5/3.2.1.5, which defines the
usual arithmetic conversions but does NOT state where they apply.
That is left to later sections in 6.3.*/3.3.*.

It is true that various sections in 6.3.*/3.3.* refer explicitly to
integral promotions occurring; these are redundant, since the values
in question would already have undergone the integral promotions
automatically (and a second integral promotion causes no change).
They do, as I said above, confirm that the intent was otherwise than
as I said previously.

Finally, there is the matter of sizeof.  If c is a char, and values
of type char are converted automatically to int, does it follow that
sizeof c should produce sizeof(int)?  No, it doesn't.  The reason
is that the operand of sizeof is defined as not being evaluated.
If it isn't evaluated, there's no value involved, and it's only
*values* ("rvalues" if you prefer) that undergo the integral promotions.

But none of this matters, because none of it ever causes an expression
to produce a different result.  Under the "as if" rule, if redundant
type conversions are required, they're not required to be *implemented*.

Followups directed to comp.std.c.
--

#define MSB(type)       (~(((unsigned type)-1)>>1))

My text in this article is in the public domain.



Tue, 11 Aug 1998 03:00:00 GMT  
 
 [ 41 post ]  Go to page: [1] [2] [3]

 Relevant Pages 
 

 
Powered by phpBB® Forum Software