ptrdiff_t

S

Stefan Ram

To make the program exit, if and only if the value l can not be
represented as an unsigned, is the following code correct?

ptrdiff_t const l = p - s;
if( l < 0 )exit( 99 );
unsigned u = l;
if( u != l )exit( 99 );

Or is there already a certain idiom well-known for that?
 
P

Peter Nilsson

Note: The author of this message requested that it not be
archived. This message will be removed from Groups in 6 days
(Nov 20, 7:45 am).
Why?!

To make the program exit, if and only if the value l can
not be represented as an unsigned, is the following code
correct?

ptrdiff_t const l = p - s;
if( l < 0 )exit( 99 );
unsigned u = l;
if( u != l )exit( 99 );

Looks okay.
  Or is there already a certain idiom well-known for that?

More obvious (to me) is something like...

if (l < 0 or UINT_MAX < l)
exit(EXIT_FAILURE);
 
S

Stefan Ram

Peter Nilsson said:
UINT_MAX < l

Before the comparision takes place, the values will
be converted to have the same type. I need to understand
more about this conversion to be able to see whether this
comparision has the intended behavior. So, to which type
will the operands be converted, and what could this mean
for the comparision semantics?
 
E

Eric Sosman

Stefan said:
Before the comparision takes place, the values will
be converted to have the same type. I need to understand
more about this conversion to be able to see whether this
comparision has the intended behavior. So, to which type
will the operands be converted, and what could this mean
for the comparision semantics?

(From earlier posts, `l' is of type ptrdiff_t, and has
already been found to be non-negative.)

If PTRDIFF_MAX < UINT_MAX, the value of `l' is converted
to unsigned int before the comparison. Conversion from a
signed to an unsigned type necessarily alters the value of a
negative number, but we already know `l >= 0' so this is not
an issue. Also, since the value of `l' is within the range
of unsigned int, there's no truncation to worry about. The
comparison takes place without surprises.

If PTRDIFF_MAX > UINT_MAX, the value of UINT_MAX is
converted to ptrdiff_t before the comparison. Since the
value of UINT_MAX is with the range of ptrdiff_t, there is
no out-of-range condition in the conversion, and UINT_MAX
survives the conversion with its value unscathed. Again, the
comparison produces no surprises.

If PTRDIFF_MAX == UINT_MAX (I'm not sure this is possible,
but padding bits can, in theory, produce many oddities), we
don't know which value is converted to the other's type, but
we know that it survives unchanged. Once again, the comparison
fails to startle anyone.
 
E

Eric Sosman

Stefan said:
Before the comparision takes place, the values will
be converted to have the same type. I need to understand
more about this conversion to be able to see whether this
comparision has the intended behavior. So, to which type
will the operands be converted, and what could this mean
for the comparision semantics?

(From earlier posts, `l' is of type ptrdiff_t, and has
already been found to be non-negative.)

If PTRDIFF_MAX < UINT_MAX, the value of `l' is converted
to unsigned int before the comparison. Conversion from a
signed to an unsigned type necessarily alters the value of a
negative number, but we already know `l >= 0' so this is not
an issue. Also, since the value of `l' is within the range
of unsigned int, there's no truncation to worry about. The
comparison takes place without surprises.

If PTRDIFF_MAX > UINT_MAX, the value of UINT_MAX is
converted to ptrdiff_t before the comparison. Since the
value of UINT_MAX is within the range of ptrdiff_t, there is
no out-of-range condition in the conversion, and UINT_MAX
survives the conversion with its value unscathed. Again, the
comparison produces no surprises.

If PTRDIFF_MAX == UINT_MAX (I'm not sure this is possible,
but padding bits can, in theory, produce many oddities), we
don't know which value is converted to the other's type, but
we know that it survives unchanged. Once again, the comparison
fails to startle anyone.
 
S

Stefan Ram

Eric Sosman said:
(From earlier posts, `l' is of type ptrdiff_t, and has
already been found to be non-negative.)
If PTRDIFF_MAX < UINT_MAX, the value of `l' is converted
to unsigned int before the comparison.

This was not obvious to me, as ISO/IEC 9899:1999 (E) contains
wording that is difficult to understand for me. First, it talks
about "ranks":

6.3.1.8 Usual arithmetic conversions

(...)

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.

Then, it tries to explain "rank" to me as:

6.3.1.1 Boolean, characters, and integers

Every integer type has an integer conversion rank
defined as follows:

<several rules I find hard to comprehend right now>

Were you aware of all those rules and have taken them into
account and then finally arrived at the conclusion quoted
above, or is there a way to see why the conclusion is true
without starting to think about the »rank« of the operands?
 
E

Eric Sosman

Stefan said:
This was not obvious to me, as ISO/IEC 9899:1999 (E) contains
wording that is difficult to understand for me. First, it talks
about "ranks":

6.3.1.8 Usual arithmetic conversions

(...)

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.

Then, it tries to explain "rank" to me as:

6.3.1.1 Boolean, characters, and integers

Every integer type has an integer conversion rank
defined as follows:

<several rules I find hard to comprehend right now>

Were you aware of all those rules and have taken them into
account and then finally arrived at the conclusion quoted
above, or is there a way to see why the conclusion is true
without starting to think about the »rank« of the operands?

I took the shortcut of "reading the intent instead of the
language." The stuff about ranks was added in C99, to handle
the population explosion of integer types (C90 had only nine;
C99 has at least eleven, plus implementation-defined extras).

The paragraph that reveals the intent is 6.2.5p6:

For any two integer types with the same signedness and
different integer conversion rank, the range of values
of the type with smaller integer conversion rank is a
subrange of the values of the other type.

So "rank" is just a generalization of the C90 notion that
"char <= short <= int <= long," showing how other integer types
fit into the picture. C99 cannot list all the integer types
(because it doesn't know what the implementation may add), so
instead it talks about their "ranks." And the stuff about
subranges says that when a lower-ranked integer is promoted
to a higher-ranked integer of the same signedness, the value
is preserved. There's a little more language relating the
ranks of corresponding signed and unsigned types, but my wife
is calling me to dinner and I haven't time to look it up now.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top