checking array indices

S

Sterten

you should probably use a run-time check:
if ( r<0 || r>98 ) ...

but there can be hundreds of array-accesses
in the program, even nested, so I prefer
a program to do this checking automatically,
like I'm used it to be in BASIC.
 
E

Eric Sosman

Giorgos said:
An architecture on which the least significant bit it used as the sign
of a value combined with a C compiler which coerces int values to
unsigned by clearing the sign bit or even by shifting it to one of the
value bits.

Then -3 would be represented as 00000111 and would be coerced to
unsigned as 00000110 which would be +3 but still less than 99.

If this happens, the language is not C. Period.

The result of converting -3 to `unsigned int' is
`UINT_MAX - 2'. Always. And since `UINT_MAX' is at
least 65535, the result will be at least 65533 and
most definitely greater than 99.
 
K

Keith Thompson

Eric Sosman said:
If this happens, the language is not C. Period.

The result of converting -3 to `unsigned int' is
`UINT_MAX - 2'. Always. And since `UINT_MAX' is at
least 65535, the result will be at least 65533 and
most definitely greater than 99.

What about a machine with 24-bit words, with UINT_MAX and INT_MAX both
set to 8388607 (2**23-1)?
 
E

Eric Sosman

Keith said:
What about a machine with 24-bit words, with UINT_MAX and INT_MAX both
set to 8388607 (2**23-1)?

What's the "what" you're concerned about? -3 would
convert to UINT_MAX - 2, as always, yielding the value
8388605 which is larger than 99 -- I'm sure that's not
what's worrying you, but I don't know what is ...
 
K

Keith Thompson

Eric Sosman said:
What's the "what" you're concerned about? -3 would
convert to UINT_MAX - 2, as always, yielding the value
8388605 which is larger than 99 -- I'm sure that's not
what's worrying you, but I don't know what is ...

A few articles upthread, I wrote:

] No, there is no negative value of type int that yields a value less
] than 99 when converted to unsigned int. (There might be exotic
] representations where this isn't the case.)

If UINT_MAX and INT_MAX both have the value 8388607 (2**23-1), then
the int value -8388558, converted to unsigned int, yields the value 50.

The context was a suggestion to use something like

assert((unsigned) i <= 99);

as an optimization of

assert(i >= 0 && i <= 99);

The check would fail on the hypothetical exotic system if i is equal
to 8388607, causing undefined behavior when i is subsequently used as
an index into a 100-element array.
 
B

Barry Schwarz

Barry Schwarz said:
On Sat, 24 Jul 2004 17:26:10 -0700, "Ricardo Gibert"

when I define
int R[99];
and then later access it with
x=R[r];C[x]=7;
...
but x happens to be <0 or >99 , then the program's behavious
becomes unpredictable.

You must mean x < 0 or x >= 99 in the above.

You can try this:

assert((unsigned) i < 99);

Why the cast. If i contains a sufficiently large negative value, your
assert will be true but your next statement will invoke undefined
behavior.

t = R;

No, there is no negative value of type int that yields a value less
than 99 when converted to unsigned int. (There might be exotic
representations where this isn't the case.)

This is only true in the "common" situation where the absolute value
of INT_MIN is only half of UINT_MAX. The standard does not require
this. It is possible for these values to be equal but opposite in
sign. It would be legal on a 32-bit system for
INT_MAX=UINT_MAX=pow(2,31)-1 and INT_MIN=-INT_MAX. (There is no
requirement that an unsigned int use the now irrelevant sign bit to
extend its range of values.) In fact, any exponent value between 31
and 16 would be compliant.

On any system where INT_MIN <= -UINT_MAX, the 99 int values
between -UINT_MAX and -UINT_MAX+98 would satisfy the assert but still
invoke undefined behavior.

A cast from int or char to unsigned does not cause undefined behavior.



But I'd still be more comfortable with

assert(i >= 0 && i < 99);

(assuming that assert is a good way to do the check in the first
place).

Obviously, but once the unsigned value has passed the assert, the
signed negative value is used as an array index and that does cause
undefined behavior.


Okay, I see I managed to misunderstand even though it should have been clear. Sorry.

In the event that the condition "INT_MIN <= -UINT_MAX" were true, you would be correct. Something that would exhibit such undefined
behavior would be a cast from long long to unsigned long as an example, but I don't think "INT_MIN <= -UINT_MAX" is ever true, since
unsigned is guaranteed to occupy the same amount of storage as an int.


But there is no requirement that an unsigned int use the sign bit to
extend its range. It is legal for INT_MIN to be -(pow(2,31)-1) and
UINT_MAX and INT_MAX both to be pow(2,31)-1.


<<Remove the del for email>>
 
R

Ricardo Gibert

Barry Schwarz said:
On Sun, 25 Jul 2004 10:58:40 -0700, "Ricardo Gibert"


On Sat, 24 Jul 2004 17:26:10 -0700, "Ricardo Gibert"

when I define
int R[99];
and then later access it with
x=R[r];C[x]=7;
...
but x happens to be <0 or >99 , then the program's behavious
becomes unpredictable.

You must mean x < 0 or x >= 99 in the above.

You can try this:

assert((unsigned) i < 99);

Why the cast. If i contains a sufficiently large negative value, your
assert will be true but your next statement will invoke undefined
behavior.

t = R;

No, there is no negative value of type int that yields a value less
than 99 when converted to unsigned int. (There might be exotic
representations where this isn't the case.)

This is only true in the "common" situation where the absolute value
of INT_MIN is only half of UINT_MAX. The standard does not require
this. It is possible for these values to be equal but opposite in
sign. It would be legal on a 32-bit system for
INT_MAX=UINT_MAX=pow(2,31)-1 and INT_MIN=-INT_MAX. (There is no
requirement that an unsigned int use the now irrelevant sign bit to
extend its range of values.) In fact, any exponent value between 31
and 16 would be compliant.

On any system where INT_MIN <= -UINT_MAX, the 99 int values
between -UINT_MAX and -UINT_MAX+98 would satisfy the assert but still
invoke undefined behavior.

A cast from int or char to unsigned does not cause undefined behavior.



But I'd still be more comfortable with

assert(i >= 0 && i < 99);

(assuming that assert is a good way to do the check in the first
place).



Obviously, but once the unsigned value has passed the assert, the
signed negative value is used as an array index and that does cause
undefined behavior.


Okay, I see I managed to misunderstand even though it should have been clear. Sorry.

In the event that the condition "INT_MIN <= -UINT_MAX" were true, you would be correct. Something that would exhibit such undefined
behavior would be a cast from long long to unsigned long as an example, but I don't think "INT_MIN <= -UINT_MAX" is ever true, since
unsigned is guaranteed to occupy the same amount of storage as an int.


But there is no requirement that an unsigned int use the sign bit to
extend its range. It is legal for INT_MIN to be -(pow(2,31)-1) and
UINT_MAX and INT_MAX both to be pow(2,31)-1.


I see that I have no choice, but to accept this as a legal possibility. I can't
find anything in the standard that precludes this. Strictly speaking, it seems
the trick is a technical error portability-wise, though useful to the compiler
writer or assembly language programmer.

Thanks for being patient with me.
 

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

No members online now.

Forum statistics

Threads
474,145
Messages
2,570,826
Members
47,371
Latest member
Brkaa

Latest Threads

Top