473,609 Members | 1,810 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

out of range array subscript

The n869 draft says:

J.2 Undefined behavior

[#1] The behavior is undefined in the following
circumstances:

-- An array subscript is out of range, even if an object
is apparently accessible with the given subscript (as
in the lvalue expression a[1][7] given the declaration
int a[4][5]) (6.5.6).

I am wondering if a cast can change this behaviour to something well
defined, ie if the las following line is ok:

int a[4][5];

a[1][7] = 3; /* <- undefined behaviour */

((int*)a[1])[7] = 42; /* defined or not? */

--
Richard
Nov 14 '05 #1
5 3428
Richard Delorme wrote:
The n869 draft says:

J.2 Undefined behavior

[#1] The behavior is undefined in the following
circumstances:

-- An array subscript is out of range, even if an object
is apparently accessible with the given subscript (as
in the lvalue expression a[1][7] given the declaration
int a[4][5]) (6.5.6).

I am wondering if a cast can change this behaviour to something well
defined, ie if the las following line is ok:

int a[4][5];

a[1][7] = 3; /* <- undefined behaviour */

((int*)a[1])[7] = 42; /* defined or not? */


Still undefined. The cast does not change the type of the object
itself, only the type of the expression you are using to access the
object.

For example, imagine an array bounds checking implementation which
represents a[1] as the triple (pointer to a[1][], offset 0, size 5).
The cast may preserve this representation, just as it would with a
pointer to a malloced area. The lvalue (a[1][], offset 0, size 5)[7]
translates into *(a[1][], offset 7, size 5), and fails on the array
bounds check that offset < size. (Or the check offset <= size, if you
had not dereferenced the pointer.)

--
Hallvard
Nov 14 '05 #2
On 3 May 2004, Hallvard B Furuseth wrote:
Richard Delorme wrote:
The n869 draft says:

J.2 Undefined behavior

[#1] The behavior is undefined in the following
circumstances:

-- An array subscript is out of range, even if an object
is apparently accessible with the given subscript (as
in the lvalue expression a[1][7] given the declaration
int a[4][5]) (6.5.6).

I am wondering if a cast can change this behaviour to something well
defined, ie if the las following line is ok:

int a[4][5];

a[1][7] = 3; /* <- undefined behaviour */

((int*)a[1])[7] = 42; /* defined or not? */


Still undefined. The cast does not change the type of the object
itself, only the type of the expression you are using to access the
object.


So let's alter it slightly just to make things unclear:

((int*)(a+1))[7] = 42; /* still UB? */

Nov 14 '05 #3
Jarno A Wuolijoki wrote:
On 3 May 2004, Hallvard B Furuseth wrote:
int a[4][5]; ((int*)a[1])[7] = 42; /* defined or not? */


Still undefined. The cast does not change the type of the object
itself, only the type of the expression you are using to access the
object.


So let's alter it slightly just to make things unclear:

((int*)(a+1))[7] = 42; /* still UB? */


Sure, still UB. `a+1' degenerates to `&a[0] + 1' = `&a[1]', so it still
refers to an object where the [7] index goes above the array bound.

OTOH, this is OK:

((int*)&a)[1*5 + 7] = 42;

because `&a' gives the address of the entire object `a', which consists
of 20 `int's, and 1*5 + 7 < 20.

--
Hallvard
Nov 14 '05 #4
On 3 May 2004, Hallvard B Furuseth wrote:
Jarno A Wuolijoki wrote:
On 3 May 2004, Hallvard B Furuseth wrote:
int a[4][5];
((int*)a[1])[7] = 42; /* defined or not? */

Still undefined. The cast does not change the type of the object
itself, only the type of the expression you are using to access the
object.


So let's alter it slightly just to make things unclear:
((int*)(a+1))[7] = 42; /* still UB? */


Sure, still UB. `a+1' degenerates to `&a[0] + 1' = `&a[1]', so it still
refers to an object where the [7] index goes above the array bound.


Wouldn't, say, a+1+2 be one as well by that logic?

a+1 becomes &a[1] and &a[1]+2 would be an out of bounds access of a[1].

Or does (int*)&a[1] somehow descend to the "subobject" in a way
mere &a[1] doesn't?

Nov 14 '05 #5
[I *think* I have all the attributions correct...]

Someone wrote:
> int a[4][5];
> ((int*)a[1])[7] = 42; /* defined or not? */ On 3 May 2004, Hallvard B Furuseth wrote:
Still undefined. The cast does not change the type of the object
itself, only the type of the expression you are using to access the
object.
Jarno A Wuolijoki wrote:
So let's alter it slightly just to make things unclear:
((int*)(a+1))[7] = 42; /* still UB? */
On 3 May 2004, Hallvard B Furuseth wrote:
Sure, still UB. `a+1' degenerates to `&a[0] + 1' = `&a[1]', so it still
refers to an object where the [7] index goes above the array bound.

In article
<news:Pi******* *************** *************** @melkinpaasi.cs .Helsinki.FI>
Jarno A Wuolijoki <jw******@cs.He lsinki.FI> writes:Wouldn't, say, a+1+2 be one as well by that logic?
Assuming "be one" means "be an instance of undefined behavior": no.
Let me give the intermediate expressions names here:
a+1 becomes &a[1] and &a[1]+2 would be an out of bounds access of a[1].
a+1 and &a[1] denote the same thing, a value of type "pointer to
array 5 of int" pointing to the row of 5 "int"s in a[1]:

int (*p)[5] = &a[1];
/*
* Now we have, e.g.:
*
* a[0]: { 0, 1, 2, 3, 4}
* a[1]: { 5, 6, 7, 8, 9}
* a[2]: {10,11,12,13,14 }
* a[3]: {15,16,17,18,19 }
*
* and p points to all of a[1].
*/

Adding 2 to this value steps forward by two of the objects to
which this points:

int (*q)[5] = p + 2;

Since "p" points to one complete row of 5 "int"s, q steps forward
by two complete rows of 5 "int"s, and now points to all of a[3].

Note that *p is an array -- it names all 5 elements of a[1] --
and *q is also an array (all 5 elements of a[3]). Because *p
and *q are arrays, they are subject to The Rule about arrays
and pointers in C, namely:

In a value context, an object of type "array N of T"
becomes a value of type "pointer to T", pointing to the
first element of that array, i.e., the one with subscript 0.

So if we write (*p)[2], that puts *p -- an array object --
into a value context to subscript it with "[2]", and thus converts
from "the entire row {5,6,7,8,9} as an object" into "a pointer
to the array's first element, i.e., a pointer to the int 5".
Subscripting by 2 is really pointer arithmetic, where to add
2 we move forward by 2 of whatever it is that this new pointer
points to -- in this case, 2 "int"s. This takes us from pointing
to the 5 to pointing to the 7, and then the last step is to
indirect again, giving the "int" 7 as an object.

Hence:

(*p)[2] += 70;

makes a[1][2] change from 7 to 77. We can write (*p) as p[0]
of course:

p[0][2] += 70; /* same thing */

and moreover, we can use pointer arithmetic on p -- as we did
to get q -- as part of the subscripting operation:

p[1][2] -= 20;

Since p[1] "means" *(p + 1), we move forward by one of the things
that "p" points to, i.e., one "array 5 of int" row in the array
named "a". Now we point to the entire row {10,11,12,13,14 }. The
indirection gets us the entire array object, which "decays" to a
pointer per The Rule for the [2] step. Subscriping this pointer
works just as before, and p[1][2] names the same single "int" as
a[2][2], which in the example above is "12" initially. Subtracting
20 from it changes a[2][2] from 12 to -8.
Or does (int*)&a[1] somehow descend to the "subobject" in a way
mere &a[1] doesn't?


Here we have &a[1] -- a pointer to the entire row {5,6,7,8,9} in
the example above -- and convert the pointer through pointer casting
into some other pointer. What exactly does this do? The rules
here are at least to some extent up to the implementation. The
"input" type (before the cast) is "int (*)[5]" or "pointer to array
5 of int". The "output" type is "int *", or "pointer to int".
The implementor gets to decide how to achieve the conversion and
what the result should be.

Suppose a hypothetical Evil Implementor decides that the rule is
"conversion of `pointer to array N of T' to `pointer to T' finds
the N-1th element of the array and gives you that pointer". (This
would be quite *surprising* but I do not believe the C standards
forbid it. It might even be the "natural" implementation on certain
ancient IBM mainframes, the ones where Fortran array subscripting
worked from the top down, as it were.) In this case, the result
of (int *)p -- where p points to the entire row {5,6,7,8,9} --
would be a pointer to the element a[1][4], currently holding 9.

Of course, the "usual" implementation is to take the *lowest*
machine byte or word address, so that (int *)p is just a pointer
to the element a[1][0], currently holding 5.

This pointer cast, like all pointer casts, should be viewed with
suspicion. ("Cast a jaundiced eye upon the pointer"? :-) See
<http://www.phrases.org .uk/bulletin_board/19/messages/133.html>)
C's history, particularly with "const", makes some pointer
casts inevitable in some code, but the more you "evit" :-) them
the better, in general. (Aside: www.m-w.com claims "evitable"
*is* a word. I thought it was a "lost positive" myself.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
1544
by: Tom Page | last post by:
Hello all I have a question that may or may not be simple - I need my three dimensional array to be of the form: array where jj and kk range from 0 to some constant fixed at the very beginnning of the program (currently 20) but goes from 0 to some boundary that depends on calculations performed within the program. I know it is possible
51
23680
by: Pedro Graca | last post by:
I run into a strange warning (for me) today (I was trying to improve the score of the UVA #10018 Programming Challenge). $ gcc -W -Wall -std=c89 -pedantic -O2 10018-clc.c -o 10018-clc 10018-clc.c: In function `main': 10018-clc.c:22: warning: array subscript has type `char' I don't like warnings ... or casts.
3
14559
by: uche | last post by:
Please give me some feed back on this issue: Here is the complier error: hexdmp.cpp: In function `void output(unsigned char, int, bool&)': hexdmp.cpp:133: error: invalid types `unsigned char' for array subscript hexdmp.cpp:146: error: invalid types `unsigned char' for array subscript hexdmp.cpp:146: error: invalid types `unsigned char' for array
3
1555
by: jock1up | last post by:
I have this array and Dim statement: Dim curSales(1 to 5) as Currency Using an If clause, I was wondering which one might verify that the array subscript called intX was valid? I realize that this has to be within the range to be valid such as 1 to 5. If intX > 1 and intX < 5 Then
13
3621
by: Ivan | last post by:
Hi, What is the best syntax to use a char to index into an array. /////////////////////////////////// For example int data; data = 1;
0
8138
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8578
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8408
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6063
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5523
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4094
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2538
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1683
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1399
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.