Topic: (Dis)Continuity of statically allocated multidimensional arrays


Author: James.Kanze@dresdner-bank.com
Date: Tue, 9 Jan 2001 23:08:34 GMT
Raw View
In article <3A56789D.6CBB4CF6@netwood.net>,
  "E. Robert Tisdale" <edwin@netwood.net> wrote:
> kanze@gabi-soft.de wrote:

> > Because of the rules concerning sizeof, on one hand,
> > and the (related) rules concerning pointer difference,
> > especially after the pointers have been cast to char*.
> > The standard does guarantee that:

> >     sizeof( a[ 0 ] ) == 8 * sizeof( int )

> > and

> >     (char*)(&a[ 0 ]) + sizeof( a[ 0 ] ) == (char*)(&a[ 1 ])

> Yes, but is

>     *((char*)(&a[ 0 ]) + sizeof( a[ 0 ] )) == *((char*)(&a[ 1 ]))

> true?
> Two pointers need not reference the same memory location
> just because the are equal.

5.10/1: "[...] Two pointers of the same type compare equal if and only
    if they are both null, both point to the same object or function,
    or both point one past the end of the same array."

--
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com
http://www.deja.com/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "E. Robert Tisdale" <edwin@netwood.net>
Date: Fri, 5 Jan 2001 17:07:16 GMT
Raw View
kayakk@my-deja.com wrote:

> So, after reading the Standard, can I assume that given
>
>     int a[8][7];
>
> this:
>
>     for(int i = 0; i < sizeof(a)/sizeof(int); ++i)
>       *(a[0] + i) = (i/7)*10 + i%7;
>
> is equivalent to:
>
>     for(int i = 0; i < sizeof(a)/sizeof(int); ++i)
>       *(&a[0][0] + i) = (i/7)*10 + i%7;
>
> and has the same effect of this in *all* implementations?
>
>     for(int i = 0; i < 8; ++i)
>       for(int j = 0; j < 7; ++j)
>         a[i][j] = 10*i + j;
>
> I know the example is contrived, but it's a way of saying that
> the array is composed by 56 elements and *nothing else*.
> Padding occurring eventually between elements,
> but not between rows.

Yes.  You can assume that this is true.
But the standard stops just short of specifying this.
Ron Natalie is arguing, I think, that this behavior
can be inferred from what the standard does specify.
What we don't know is why the standard
does not specify this behavior explicitly
leaving the question open to interpretation.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: James Kuyper <kuyper@wizard.net>
Date: Fri, 5 Jan 2001 17:08:55 GMT
Raw View
kayakk@my-deja.com wrote:
...
> The first post in this thread was because of a question of mine in
> c.l.c++
>
> So, after reading the Standard, can I assume that given
>
> int a[8][7];
>
> this:
> for(int i=0;i<sizeof(a)/sizeof(int);++i)
>   *(a[0]+i)=(i/7)*10+i%7;
>
> is equivalent to:
> for(int i=0;i<sizeof(a)/sizeof(int);++i)
>   *(&a[0][0]+i)=(i/7)*10+i%7;
>
> and has the same effect of this in *all* implementations?

No - &a[0][0] points to a[0], which is an array of length 7. As such,
it's undefined behavior to add any number larger than 7 to that pointer,
and it's undefined behavior to dereference that pointer after adding any
number larger than 6 to it. The standard guarantees that a[1] is
allocated immediately after a[0], but this is an fact that can only be
demonstrated through the use of pointers to unsigned char, which are
given special exemptions in the standard:

*(int*)( (unsigned char*)&a[0][0] + i*sizeof(a[0][0])) =
 (i/7)*10 + i%7;

I know this is clumsy, but it's a consequence of wording that was
selected to allow implementation of run-time array bounds checking. In
practice, the overhead of such checking is so high that only a few
compilers implement it, and even they provide it as a debugging option,
not as the default. If (heaven forbid! ;-) you wanted to be practical,
rather than pedantic like me, your code will probably work on just about
any implementation you're ever likely to run it on.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "E. Robert Tisdale" <edwin@netwood.net>
Date: Fri, 5 Jan 2001 17:23:20 GMT
Raw View
James Dennett wrote:

> kayakk@my-deja.com wrote:
>
> > So, after reading the Standard, can I assume that given
> >
> >     int a[8][7];
> >
> > this:
> >
> >     for (int i = 0; i < sizeof(a)/sizeof(int); ++i)
> >       *(a[0] + i) = (i/7)*10 + i%7;
> >
> > is equivalent to:
> >
> >     for (int i = 0; i < sizeof(a)/sizeof(int); ++i)
> >       *(&a[0][0] + i) = (i/7)*10 + i%7;

If this

> No.  Index out of bounds, undefined behavior.
> In both cases.  (I'm out on a limb here,
> half expecting to be shot down by a helpful language lawyer.)
>
> a[0] is an array of 7 elements.
>
> a[0] + 0 is fine, it refers to the address of the first element.
> a[0] + i, for i > 6, is an error.  You can't go past the end.
>
> This has nothing to do
> with whether the array of contiguous in memory
> and everything to do with valid pointer arithmetic.

is true, how can you know that this

> (There are no gaps in arrays beyond those
>  which already exist in their individual elements.)

is true?
The C and C++ programming languages specify pointers --
not machine addresses.
The whole notion of contiguous elements in array a
depends upon an unbroken sequence of pointers.
If you can't reference all of the elements of a
through that unbroken sequence of pointers,
it doesn't mean anything to say that they are contiguous.

> > I know the example is contrived, but it's a way of saying that
> > the array is composed by 56 elements and *nothing else*.
> > Padding occurring eventually between elements,
> > but not between rows.
>
> It says more than that.  It assumes that you can iterate a single pointer
> over _all_ of the one dimensional arrays which make up a.
> You can't (well, not completely portably)
> because C++ only allows pointer arithmetic within a single array.
>
> Having said that, every C++ implementation
> with which I've ever worked allows your assumption to hold
> and I'm sure there's plenty of C/C++ code out there
> which uses (abuses?) this fact.
> (I've written semi-portable code myself which does much worse.)

That's pretty good evidence for arguing that
a defacto standard already exists
so it really doesn't matter what the standards documents say.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: kayakk@my-deja.com
Date: Fri, 5 Jan 2001 17:23:40 GMT
Raw View
In article <3A553DC6.237E901E@evtechnology.com>,
  James Dennett <james@evtechnology.com> wrote:
> kayakk@my-deja.com wrote:
> >
> > Hi,
> >
> > Ron Natalie wrote:
> > >
> > >
> > > James Kuyper wrote:
> > >
> > > > > >
> > > > > >     (unsigned char*)(&array[x][0])
> > > > > >       == (unsigned char*)(&array[x][0]) + 10u*sizeof(int)*x;
> > > > >
> > > > > You are confused.  The standard does NOT specify
> > > > > any particular arrangement of computer memory.
> > > >
> > > > The standard (1.8p5) says that "An object of POD 4) type (3.9)
shall
> > > > occupy contiguous bytes of storage."
> > > > 8.3.4p1: "An object of array type contains a contiguously
allocated
> > > > non-empty set of N sub-objects of type T".
> > > > Paragraph 9 of that same section says: "Note: it follows from
all
> > this
> > > > that arrays in C++ are stored row-wise (last subscript varies
> > fastest)
> > > > and that the first subscript in the declaration helps determine
the
> > > > amount of storage consumed by than array but plays no other
part in
> > > > subscript calculations."
> > >
> > > Correct, there really aren't multidimensional arrays, just arrays
of
> > > other arrays.  It is clear from the required behavior of various
> > > things in the standard, that a multidimensional array has a clear
> > > an unambiguous layout with respect to the objects themselves (the
> > > interior arrangment of an object is not specified), but the size
> > (sizeof)
> > > must include the padding to pack them together in an array, and by
> > > induction, arrays pack inside other arrays in a defined fashion.
> > >
> >
> > The first post in this thread was because of a question of mine in
> > c.l.c++
> >
> > So, after reading the Standard, can I assume that given
> >
> > int a[8][7];
> >
> > this:
> > for(int i=0;i<sizeof(a)/sizeof(int);++i)
> >   *(a[0]+i)=(i/7)*10+i%7;
> >
> > is equivalent to:
> > for(int i=0;i<sizeof(a)/sizeof(int);++i)
> >   *(&a[0][0]+i)=(i/7)*10+i%7;
>
> No.  Index out of bounds, undefined behaviour.  In both cases.
> (I'm out on a limb here, half expecting to be shot down by a helpful
> language lawyer.)
>
> a[0] is an array of 7 elements.
>
> a[0] + 0 is fine, it refers to the address of the first element.
> a[0] + i, for i > 6, is an error.  You can't go past the end.
>
> This has nothing to do with whether the array of contiguous in
> memory, and everything to do with valid pointer arithmetic.
>
> (There are no gaps in arrays beyond those which already exist
> in their individual elements.)
>
> > I know the example is contrived, but it's a way of saying the array
is
> > composed by 56 elements and *nothing else*. Padding occurring
> > eventually between elements, but not between rows.
>
> It says more than that.  It assumes that you can iterate a single
pointer
> over _all_ of the one dimensional arrays which make up a.  You can't
> (well, not completely portably) because C++ only allows pointer
arithmetic
> within a single array.
>
> Having said that, every C++ implementation with which I've ever
> worked allows your assumption to hold, and I'm sure there's plenty of
> C/C++ code out there which uses (abuses?) this fact.  (I've written
> semi-portable code myself which does much worse.)

Well, but if
sizeof(T[N]) == sizeof(T)*N
and
sizeof(T[M][N])==sizeof(T[N])*M==sizeof(T)*N*M,

I think I *must* be able to iterate a single pointer over the whole
structure. What parts of the standard prohibit me from doing that? I
mean, we all aggree in saying that int a[3][4] is memorized as:

a[0][0] a[0][1] a[0][2] a[0][3] <-a[0]
a[1][0] a[1][1] a[1][2] a[1][3] <-a[1]
a[2][0] a[2][1] a[2][2] a[2][3] <-a[2]

but I can view the thing as:

a[0][0] a[0][1] a[0][2] a[0][3] * a[1][0] a[1][1] a[1][2] a[1][3] * a[2]
[0] a[2][1] a[2][2] a[2][3] <-a

* no padding, nothing here!

As I read the standard, there's no space beetween a[0][3] and a[1][0].
Why wouldn't a pointer be allowed to change its value from
&a[0][3]
to
&a[1][0]
thru an increment?

I mean: &a[0][3] is a pointer to int. Since there are 3 ints before the
elements it points to, and there are 8 other ints after it, why cannot
I move the pointer safely (and portably) inside all a's elements?

You are right: most C and C++ programmers expect it to work. But is
there anybody who can say it is *not* implementation defined?

>
> -- James Dennett <jdennett@acm.org>
>

Best Regards,

Giuseppe Polverini


Sent via Deja.com
http://www.deja.com/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Ron Natalie <ron@spamcop.net>
Date: Fri, 5 Jan 2001 18:06:42 GMT
Raw View

"E. Robert Tisdale" wrote:
>
> is true?
> The C and C++ programming languages specify pointers --
> not machine addresses.


> The whole notion of contiguous elements in array a
> depends upon an unbroken sequence of pointers.
> If you can't reference all of the elements of a
> through that unbroken sequence of pointers,
> it doesn't mean anything to say that they are contiguous.

The standard says (8.3.4/1) "An object of array type contains
a contiguously allocated non-empty set of N sub-objects of type T"

Furthermore the statements about what sizeof means for elements
and arrays guarantees successive memory locations.  There just
is NOT any way to introduce holes between array elements as you
suggest might happen.  The padding necessary to pack more than
one object together in memory needs to be within the object itself.


> > It says more than that.  It assumes that you can iterate a single pointer
> > over _all_ of the one dimensional arrays which make up a.

This is about the only real argument.  Nothing says that pointers
have to be convetable this way, which is the only thing that casts
a shadow on the problem.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: James Kuyper <kuyper@wizard.net>
Date: Sat, 6 Jan 2001 00:01:54 GMT
Raw View
"E. Robert Tisdale" wrote:
>
> kayakk@my-deja.com wrote:
>
> > So, after reading the Standard, can I assume that given
> >
> >     int a[8][7];
> >
> > this:
> >
> >     for(int i = 0; i < sizeof(a)/sizeof(int); ++i)
> >       *(a[0] + i) = (i/7)*10 + i%7;
> >
> > is equivalent to:
> >
> >     for(int i = 0; i < sizeof(a)/sizeof(int); ++i)
> >       *(&a[0][0] + i) = (i/7)*10 + i%7;
> >
> > and has the same effect of this in *all* implementations?
> >
> >     for(int i = 0; i < 8; ++i)
> >       for(int j = 0; j < 7; ++j)
> >         a[i][j] = 10*i + j;
> >
> > I know the example is contrived, but it's a way of saying that
> > the array is composed by 56 elements and *nothing else*.
> > Padding occurring eventually between elements,
> > but not between rows.
>
> Yes.  You can assume that this is true.

As long as you don't use a compiler in a mode that performs run-time
array-bounds checking.

> But the standard stops just short of specifying this.
> Ron Natalie is arguing, I think, that this behavior
> can be inferred from what the standard does specify.
> What we don't know is why the standard
> does not specify this behavior explicitly
> leaving the question open to interpretation.

I believe that it wasn't specified, precisely because the authors wanted
to allow (but not mandate!) run-time array-bounds checking.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: kanze@gabi-soft.de
Date: Sat, 6 Jan 2001 00:23:21 GMT
Raw View
"E. Robert Tisdale" <edwin@netwood.net> writes:

|>  If this

|>  > No.  Index out of bounds, undefined behavior.  In both cases.
|>  > (I'm out on a limb here, half expecting to be shot down by a
|>  > helpful language lawyer.)

|>  > a[0] is an array of 7 elements.

|>  > a[0] + 0 is fine, it refers to the address of the first element.
|>  > a[0] + i, for i > 6, is an error.  You can't go past the end.

|>  > This has nothing to do with whether the array of contiguous in
|>  > memory and everything to do with valid pointer arithmetic.

|>  is true, how can you know that this

|>  > (There are no gaps in arrays beyond those
|>  >  which already exist in their individual elements.)

|>  is true?

Because of the rules concerning sizeof, on one hand, and the (related)
rules concerning pointer difference, especially after the pointers have
been cast to char*.  The standard does guarantee that:

    sizeof( a[ 0 ] ) =3D=3D 8 * sizeof( int )
and
    (char*)(&a[ 0 ]) + sizeof( a[ 0 ] ) =3D=3D (char*)(&a[ 1 ])

If you can figure any way of adding additional padding and still meeting
those requirements, maybe the padding is legal.

    [...]
|>  > Having said that, every C++ implementation with which I've ever
|>  > worked allows your assumption to hold and I'm sure there's plenty
|>  > of C/C++ code out there which uses (abuses?) this fact.  (I've
|>  > written semi-portable code myself which does much worse.)

How about the old CenterLine compilers?  I know that they used fat
pointers, in order to do bounds checking on pointer arithmetic.  I don't
know how far they took it, however.

|>  That's pretty good evidence for arguing that a defacto standard
|>  already exists so it really doesn't matter what the standards
|>  documents say.

:-) A bit like two's complement, or all data pointers have the same
size, right.  (I"ve actualy used machines where one or the other was
false, but long before I knew C.)

--=20
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: James Kuyper <kuyper@wizard.net>
Date: Sat, 6 Jan 2001 00:27:27 GMT
Raw View
kayakk@my-deja.com wrote:
...
> Well, but if
> sizeof(T[N]) == sizeof(T)*N
> and
> sizeof(T[M][N])==sizeof(T[N])*M==sizeof(T)*N*M,
>
> I think I *must* be able to iterate a single pointer over the whole
> structure. What parts of the standard prohibit me from doing that? I

Nothing prohibits you from doing it - that's not how the standard is
written. What the standard says in section 5.7p5, regarding p+i, where p
is a pointer and i is an integer expression:

"... If both the pointer operand and the result point to elements of the
same array object, or one past the last element of the array object, the
evaluation shall not produce overflow; otherwise the behavior is
undefined."

By extension, this also applies to the special case of p+=i, and
therefore also to p++ and ++p.

The tricky part of this is that &a[0][0] points to an element of the
array 'a[0]'; it does NOT point to an element of the array 'a'. The
elements of the array 'a' have the type 'int[N]', not 'int'. &a[1][0] is
a pointer to an int, not to an 'int[N]'. Therefore, you can get
undefined behavior whenever you use pointer arithmetic, starting with
&a[0][0], to create a pointer that points outside the valid range for
the array 'a[0]'.

Now, getting back to "not prohibited" - the standard only says that this
produces undefined behavior. It's up to you whether or not you want to
risk causing unpredictable results, including possibly a failure to
compile. An implementation is free to define the behavior, even if the
standard leaves it undefined. In fact, most implementations do define it
in exactly the way you'd expect.

There's only a few implementations which provide, usually only as a
debugging aid, a compilation mode in which run-time bounds-checking is
performed. In that case, the "undefined behavior" usually takes the form
of an error message, possible followed by a call to abort().


...
> As I read the standard, there's no space beetween a[0][3] and a[1][0].
> Why wouldn't a pointer be allowed to change its value from
> &a[0][3]
> to
> &a[1][0]
> thru an increment?
>
> I mean: &a[0][3] is a pointer to int. Since there are 3 ints before the
> elements it points to, and there are 8 other ints after it, why cannot
> I move the pointer safely (and portably) inside all a's elements?

Because the portions of the standard I've cited allow an implementor to
do run-time bounds-checking, and your code would violate such checking.

> You are right: most C and C++ programmers expect it to work. But is
> there anybody who can say it is *not* implementation defined?

The standard: it says that it's undefined, which is a different
category. "implementation defined" means that an implementation is
required to document it. "undefined" means that an implementation is
free to leave the behavior undocumented.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: kanze@gabi-soft.de
Date: Sat, 6 Jan 2001 00:28:15 GMT
Raw View
"E. Robert Tisdale" <edwin@netwood.net> writes:

|>  kayakk@my-deja.com wrote:

|>  > So, after reading the Standard, can I assume that given

|>  >     int a[8][7];

|>  > this:

|>  >     for(int i =3D 0; i < sizeof(a)/sizeof(int); ++i)
|>  >       *(a[0] + i) =3D (i/7)*10 + i%7;

|>  > is equivalent to:

|>  >     for(int i =3D 0; i < sizeof(a)/sizeof(int); ++i)
|>  >       *(&a[0][0] + i) =3D (i/7)*10 + i%7;

|>  > and has the same effect of this in *all* implementations?

|>  >     for(int i =3D 0; i < 8; ++i)
|>  >       for(int j =3D 0; j < 7; ++j)
|>  >         a[i][j] =3D 10*i + j;

|>  > I know the example is contrived, but it's a way of saying that the
|>  > array is composed by 56 elements and *nothing else*.  Padding
|>  > occurring eventually between elements, but not between rows.

|>  Yes.  You can assume that this is true.  But the standard stops just
|>  short of specifying this.  Ron Natalie is arguing, I think, that
|>  this behavior can be inferred from what the standard does specify.
|>  What we don't know is why the standard does not specify this
|>  behavior explicitly leaving the question open to interpretation.

The C standard was designed to explicitly allow "fat" pointers, pointers
with additional range checking information.  I'm not quite sure how this
affects &a[0][0], since you can definitly take the address of the first
element of an array, then use it to access further elements, but I think
that the first deindexing returns an array of 8 int's, and that the
pointer generated by the & operator after the second index is allowed to
consider this as its upper bound.

What I am sure of is that a[9][0] is illegal, even though the address
calculations would give an address in the array a.  I think that the old
CenterLine compilers would even trigger an error in this case.

--=20
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Ron Natalie <ron@spamcop.net>
Date: Mon, 8 Jan 2001 16:45:59 GMT
Raw View

"E. Robert Tisdale" wrote:
>

> Yes.  You can assume that this is true.
> But the standard stops just short of specifying this.
> Ron Natalie is arguing, I think, that this behavior
> can be inferred from what the standard does specify.
> What we don't know is why the standard
> does not specify this behavior explicitly
> leaving the question open to interpretation.
>
There's nothing open to interpretation.  There's no need
for any more verbiage in the standard.  A 2-dimensional
array in C++ is an array of arrays (8.3.4).

The standard explicitly says that arrays are packed in
consecutive memory locations.  Any padding needed must
be included inside the object (and is counted in it's
size as computed by sizeof).

5.3.3/2 speicifically says that sizeof(T[n]) is n*sizeof(T)

It directly holds that an array[m] of a type T[n] is then
  m * sizeof(T[n])
which supstituting the rule again is
  m * n * T

It's is clear and unambiguous in the standard.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "E. Robert Tisdale" <edwin@netwood.net>
Date: Mon, 8 Jan 2001 17:07:50 GMT
Raw View
kanze@gabi-soft.de wrote:

> Because of the rules concerning sizeof, on one hand,
> and the (related) rules concerning pointer difference,
> especially after the pointers have been cast to char*.
> The standard does guarantee that:
>
>     sizeof( a[ 0 ] ) == 8 * sizeof( int )
>
> and
>
>     (char*)(&a[ 0 ]) + sizeof( a[ 0 ] ) == (char*)(&a[ 1 ])

Yes, but is

    *((char*)(&a[ 0 ]) + sizeof( a[ 0 ] )) == *((char*)(&a[ 1 ]))

true?
Two pointers need not reference the same memory location
just because the are equal.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: kayakk@my-deja.com
Date: Mon, 8 Jan 2001 23:14:51 GMT
Raw View
In article <3A56789D.6CBB4CF6@netwood.net>,
  "E. Robert Tisdale" <edwin@netwood.net> wrote:
> kanze@gabi-soft.de wrote:
>
> > Because of the rules concerning sizeof, on one hand,
> > and the (related) rules concerning pointer difference,
> > especially after the pointers have been cast to char*.
> > The standard does guarantee that:
> >
> >     sizeof( a[ 0 ] ) == 8 * sizeof( int )
> >
> > and
> >
> >     (char*)(&a[ 0 ]) + sizeof( a[ 0 ] ) == (char*)(&a[ 1 ])
>
> Yes, but is
>
>     *((char*)(&a[ 0 ]) + sizeof( a[ 0 ] )) == *((char*)(&a[ 1 ]))
>
> true?
> Two pointers need not reference the same memory location
> just because the are equal.
>

Really? So computers are not so deterministic as I used to think ;)
I mean, I know the quirks of the old 16 bit memory model on Intel
processors, where you could have different pointers referencing the
same location... (I never understood why they did such a silly thing!),
but I thought it was granted for sure that equal pointers would
reference the same memory.
I mean: how could the processor diambiguate among them?

Perhaps I may lack knowledge of a particular architecture...

Best Regards,

Giuseppe Polverini


Sent via Deja.com
http://www.deja.com/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: James Kuyper <kuyper@wizard.net>
Date: Wed, 3 Jan 2001 22:53:31 GMT
Raw View
"E. Robert Tisdale" wrote:
>
> The first thing we do, let's kill all the lawyers.
>                 -- Wm. Shakespeare, "Henry VI", Part IV
>
> James Kuyper wrote:
>
> > Josh Sebastian wrote:
...
> > > For example, given:
> > >
> > >     int array[10][10];
> > >
> > > Is the following true?
> > >
> > >     &array[x][0] == &array[0][0] + 10 * x; // 0 <= x < 10
> >
> > Almost.
> > The thing that governs the pointer &array[0][0] is array[0],
> > not array itself.  Adding 10*x to that pointer
> > would move that pointer outside the valid range for array[0].
> > It's legal for a implementation to fail
> > (for instance by halting your program)
> > when evaluating &array[0][0] + n for any n < 0 or n > 10.
> > Furthermore, it would be legal for it to fail
> > when evaluating *(&array[0][0] + n) for any n < 0 or n >= 10.
> > The difference in the upper limits is deliberate.
> > Such an implementation could be useful for debugging purposes,
> > though it would probably be unacceptably slow for actual production code.
> >
> > However, the following statements are guaranteed true:
> >
> >         &array[x] == &array[0] + x;     // 0 <= x and x <= 10
> >         sizeof(array[0]) == 10u*sizeof(array[0][0]);
> >
> > Section 3.9 says that
> > any object of a POD type can be copied to an array
> > of sizeof(object) 'char' or 'unsigned char' elements and back again,
> > preserving it's value.
> > The text could be read as endorsing only copies using std::memcpy()
> > but that certainly wasn't the intent.
> > If the copy is done by an explicit loop, then an implementation
> > that used run-time range checking on (char*) pointers
> > based upon sub-array sizes would be nonconforming.
> > Therefore, the following should also be true:
> >
> >     (unsigned char*)(&array[x][0])
> >       == (unsigned char*)(&array[x][0]) + 10u*sizeof(int)*x;
>
> You are confused.  The standard does NOT specify
> any particular arrangement of computer memory.

The standard (1.8p5) says that "An object of POD 4) type (3.9) shall
occupy contiguous bytes of storage."
8.3.4p1: "An object of array type contains a contiguously allocated
non-empty set of N sub-objects of type T".
Paragraph 9 of that same section says: "Note: it follows from all this
that arrays in C++ are stored row-wise (last subscript varies fastest)
and that the first subscript in the declaration helps determine the
amount of storage consumed by than array but plays no other part in
subscript calculations." As a Note, paragraph 9 is not normative, but it
correctly summarizes the contents of the previous paragraphs, which are
normative, and which DO specify some aspects of the arrangement of
computer memory. Not in the physical sense - the memory could physically
reside anywhere, in an arbitrary sequence - but in the sense of the
connection between array declarations and pointer arithmetic.

> There is, as you have shown, no legal way
> for the programmer to access an element out side of an array.
> If it is the intent of the standards committee(s)
> to specify the arrangement of two dimensional
> and higher dimensional arrays in memory
> then they should include language that does so explicitly
> and NOT leave the issue up to questionable interpretation.
>
> Typically, the computer architecture and the operating system
> conspire together to give the programmer an "illusion"
> of a linear memory space.  There is nothing in the standard

I was only talking in terms of that illusion. I agree that the standard
says nothing about the physical location of memory, but what it says
about arrays and pointer arithmetic adds up to requiring that "in the
illusion" (i.e. with respect to pointer operations), arrays are stored
contiguously.

> that prohibits the compiler from participating in this conspiracy.
> There are good reasons, such as avoiding resonance in caches,
> for padding the rows of a two dimensional array with an extra element.
> Nothing that you have said so far prevents the compiler
> from doing this automatically for the programmer.

5.3.3p2: "... This implies that the size of an array of _n_ elements is
_n_ times the size of an element." When combined with the rules
governing pointer arithmetic, that prohibits such padding. If you want
to give your compiler the freedom to perform such an optimization,
you'll have to do something like:

struct {
 struct {
  int r[10];
 } a[8];
} x;

Then x.a[col].r[row] is very similar syntactically to a two-dimensional
array access, but with the freedom to make sizeof(x.a[0]) >=
10*sizeof(x.a[0].r[0]).

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Ron Natalie <ron@spamcop.net>
Date: Thu, 4 Jan 2001 19:50:33 GMT
Raw View

James Kuyper wrote:

> > >
> > >     (unsigned char*)(&array[x][0])
> > >       == (unsigned char*)(&array[x][0]) + 10u*sizeof(int)*x;
> >
> > You are confused.  The standard does NOT specify
> > any particular arrangement of computer memory.
>
> The standard (1.8p5) says that "An object of POD 4) type (3.9) shall
> occupy contiguous bytes of storage."
> 8.3.4p1: "An object of array type contains a contiguously allocated
> non-empty set of N sub-objects of type T".
> Paragraph 9 of that same section says: "Note: it follows from all this
> that arrays in C++ are stored row-wise (last subscript varies fastest)
> and that the first subscript in the declaration helps determine the
> amount of storage consumed by than array but plays no other part in
> subscript calculations."

Correct, there really aren't multidimensional arrays, just arrays of
other arrays.  It is clear from the required behavior of various
things in the standard, that a multidimensional array has a clear
an unambiguous layout with respect to the objects themselves (the
interior arrangment of an object is not specified), but the size (sizeof)
must include the padding to pack them together in an array, and by
induction, arrays pack inside other arrays in a defined fashion.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: James Kuyper <kuyper@wizard.net>
Date: Thu, 4 Jan 2001 21:56:21 GMT
Raw View
Ron Natalie wrote:
...
> Correct, there really aren't multidimensional arrays, just arrays of
> other arrays.  It is clear from the required behavior of various
> things in the standard, that a multidimensional array has a clear
> an unambiguous layout with respect to the objects themselves (the
> interior arrangment of an object is not specified), but the size (sizeof)
> must include the padding to pack them together in an array, and by
> induction, arrays pack inside other arrays in a defined fashion.

I'm not quite sure whether or nor you're agreeing with me. Assume that T
is an arbitrary (POD?) type, and N and M are integer constant
expressions with positive values small enough that the following
declarations don't overflow available memory:

 T v[N];
 T a[M][N];

I believe that the standard requires that sizeof(v)==N*sizeof(T), and
that sizeof(a)=M*sizeof(v). Is that consistent with what you're saying
about padding?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Ron Natalie <ron@spamcop.net>
Date: Thu, 4 Jan 2001 22:27:30 GMT
Raw View

James Kuyper wrote:

>         T v[N];
>         T a[M][N];
>
> I believe that the standard requires that sizeof(v)==N*sizeof(T), and
> that sizeof(a)=M*sizeof(v). Is that consistent with what you're saying
> about padding?
>
I am agreeing with you.  Arrays are packed tight (whether the elements
are POD or not) because if there is padding required internal to the
object being packed, it's already considered in the 'sizeof' the object.

struct T {
   double x;
   char   y;
};

on a machine where doubles need 8 byte alignment (and are 8 bytes long
themselves) would yield:
 sizeof(T) = 8
 sizeof v[N] = N* sizeof (T);
 sizeof a[M][N] = N * sizeof (T[M]) = N * M * sizeof (T)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: kayakk@my-deja.com
Date: Fri, 5 Jan 2001 01:03:41 GMT
Raw View
Hi,

Ron Natalie wrote:
>
>
> James Kuyper wrote:
>
> > > >
> > > >     (unsigned char*)(&array[x][0])
> > > >       == (unsigned char*)(&array[x][0]) + 10u*sizeof(int)*x;
> > >
> > > You are confused.  The standard does NOT specify
> > > any particular arrangement of computer memory.
> >
> > The standard (1.8p5) says that "An object of POD 4) type (3.9) shall
> > occupy contiguous bytes of storage."
> > 8.3.4p1: "An object of array type contains a contiguously allocated
> > non-empty set of N sub-objects of type T".
> > Paragraph 9 of that same section says: "Note: it follows from all
this
> > that arrays in C++ are stored row-wise (last subscript varies
fastest)
> > and that the first subscript in the declaration helps determine the
> > amount of storage consumed by than array but plays no other part in
> > subscript calculations."
>
> Correct, there really aren't multidimensional arrays, just arrays of
> other arrays.  It is clear from the required behavior of various
> things in the standard, that a multidimensional array has a clear
> an unambiguous layout with respect to the objects themselves (the
> interior arrangment of an object is not specified), but the size
(sizeof)
> must include the padding to pack them together in an array, and by
> induction, arrays pack inside other arrays in a defined fashion.
>

The first post in this thread was because of a question of mine in
c.l.c++

So, after reading the Standard, can I assume that given

int a[8][7];

this:
for(int i=0;i<sizeof(a)/sizeof(int);++i)
  *(a[0]+i)=(i/7)*10+i%7;

is equivalent to:
for(int i=0;i<sizeof(a)/sizeof(int);++i)
  *(&a[0][0]+i)=(i/7)*10+i%7;

and has the same effect of this in *all* implementations?

for(int i=0;i<8;++i)
  for(int j=0;j<7;++j)
    a[i][j]=10*i+j;

I know the example is contrived, but it's a way of saying the array is
composed by 56 elements and *nothing else*. Padding occurring
eventually between elements, but not between rows.

TIA

Giuseppe Polverini


Sent via Deja.com
http://www.deja.com/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: James Dennett <james@evtechnology.com>
Date: Fri, 5 Jan 2001 01:50:45 GMT
Raw View
kayakk@my-deja.com wrote:
>
> Hi,
>
> Ron Natalie wrote:
> >
> >
> > James Kuyper wrote:
> >
> > > > >
> > > > >     (unsigned char*)(&array[x][0])
> > > > >       == (unsigned char*)(&array[x][0]) + 10u*sizeof(int)*x;
> > > >
> > > > You are confused.  The standard does NOT specify
> > > > any particular arrangement of computer memory.
> > >
> > > The standard (1.8p5) says that "An object of POD 4) type (3.9) shall
> > > occupy contiguous bytes of storage."
> > > 8.3.4p1: "An object of array type contains a contiguously allocated
> > > non-empty set of N sub-objects of type T".
> > > Paragraph 9 of that same section says: "Note: it follows from all
> this
> > > that arrays in C++ are stored row-wise (last subscript varies
> fastest)
> > > and that the first subscript in the declaration helps determine the
> > > amount of storage consumed by than array but plays no other part in
> > > subscript calculations."
> >
> > Correct, there really aren't multidimensional arrays, just arrays of
> > other arrays.  It is clear from the required behavior of various
> > things in the standard, that a multidimensional array has a clear
> > an unambiguous layout with respect to the objects themselves (the
> > interior arrangment of an object is not specified), but the size
> (sizeof)
> > must include the padding to pack them together in an array, and by
> > induction, arrays pack inside other arrays in a defined fashion.
> >
>
> The first post in this thread was because of a question of mine in
> c.l.c++
>
> So, after reading the Standard, can I assume that given
>
> int a[8][7];
>
> this:
> for(int i=0;i<sizeof(a)/sizeof(int);++i)
>   *(a[0]+i)=(i/7)*10+i%7;
>
> is equivalent to:
> for(int i=0;i<sizeof(a)/sizeof(int);++i)
>   *(&a[0][0]+i)=(i/7)*10+i%7;

No.  Index out of bounds, undefined behaviour.  In both cases.
(I'm out on a limb here, half expecting to be shot down by a helpful
language lawyer.)

a[0] is an array of 7 elements.

a[0] + 0 is fine, it refers to the address of the first element.
a[0] + i, for i > 6, is an error.  You can't go past the end.

This has nothing to do with whether the array of contiguous in
memory, and everything to do with valid pointer arithmetic.

(There are no gaps in arrays beyond those which already exist
in their individual elements.)

> I know the example is contrived, but it's a way of saying the array is
> composed by 56 elements and *nothing else*. Padding occurring
> eventually between elements, but not between rows.

It says more than that.  It assumes that you can iterate a single pointer
over _all_ of the one dimensional arrays which make up a.  You can't
(well, not completely portably) because C++ only allows pointer arithmetic
within a single array.

Having said that, every C++ implementation with which I've ever
worked allows your assumption to hold, and I'm sure there's plenty of
C/C++ code out there which uses (abuses?) this fact.  (I've written
semi-portable code myself which does much worse.)

-- James Dennett <jdennett@acm.org>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "E. Robert Tisdale" <edwin@netwood.net>
Date: Mon, 25 Dec 2000 00:51:05 GMT
Raw View
The first thing we do, let's kill all the lawyers.
                -- Wm. Shakespeare, "Henry VI", Part IV

James Kuyper wrote:

> Josh Sebastian wrote:
>
> > I've been told that the Standard does not guarantee that
> > elements of multidimensional arrays occupy contiguous memory.
> > But the way I read the Standard, they must.
>
> That's incorrect.  What is correct is that
> you can't safely move a pointer outside the valid range
> of the array that it's a part of,
> even if that array is itself a part of a larger array
> in which case it would be guaranteed contiguous.
>
> > For example, given:
> >
> >     int array[10][10];
> >
> > Is the following true?
> >
> >     &array[x][0] == &array[0][0] + 10 * x; // 0 <= x < 10
>
> Almost.
> The thing that governs the pointer &array[0][0] is array[0],
> not array itself.  Adding 10*x to that pointer
> would move that pointer outside the valid range for array[0].
> It's legal for a implementation to fail
> (for instance by halting your program)
> when evaluating &array[0][0] + n for any n < 0 or n > 10.
> Furthermore, it would be legal for it to fail
> when evaluating *(&array[0][0] + n) for any n < 0 or n >= 10.
> The difference in the upper limits is deliberate.
> Such an implementation could be useful for debugging purposes,
> though it would probably be unacceptably slow for actual production code.
>
> However, the following statements are guaranteed true:
>
>         &array[x] == &array[0] + x;     // 0 <= x and x <= 10
>         sizeof(array[0]) == 10u*sizeof(array[0][0]);
>
> Section 3.9 says that
> any object of a POD type can be copied to an array
> of sizeof(object) 'char' or 'unsigned char' elements and back again,
> preserving it's value.
> The text could be read as endorsing only copies using std::memcpy()
> but that certainly wasn't the intent.
> If the copy is done by an explicit loop, then an implementation
> that used run-time range checking on (char*) pointers
> based upon sub-array sizes would be nonconforming.
> Therefore, the following should also be true:
>
>     (unsigned char*)(&array[x][0])
>       == (unsigned char*)(&array[x][0]) + 10u*sizeof(int)*x;

You are confused.  The standard does NOT specify
any particular arrangement of computer memory.
There is, as you have shown, no legal way
for the programmer to access an element out side of an array.

If it is the intent of the standards committee(s)
to specify the arrangement of two dimensional
and higher dimensional arrays in memory
then they should include language that does so explicitly
and NOT leave the issue up to questionable interpretation.

Typically, the computer architecture and the operating system
conspire together to give the programmer an "illusion"
of a linear memory space.  There is nothing in the standard
that prohibits the compiler from participating in this conspiracy.
There are good reasons, such as avoiding resonance in caches,
for padding the rows of a two dimensional array with an extra element.
Nothing that you have said so far prevents the compiler
from doing this automatically for the programmer.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Ron Natalie <ron@sensor.com>
Date: Mon, 11 Dec 2000 17:43:28 GMT
Raw View

Josh Sebastian wrote:
>
> I've been told that the Standard does not guarantee that elements of
> multidimensional arrays occupy contiguous memory. But the way I read
> the Standard, they must.

You are right, whoever was talking to you is wrong.  The elements of
the array must be contiguous (any padding for an arbitrary object is
already included in it's size).  Array elements are contiguous

There really ain't no such thing as a multidimensional array.  All you
have is an array of arrays.  The elements in the inner array are contiguous
and the outer array of arrays is contiguous.

> 8.3.4/1
> "An object of array type contains a contiguously allocated non-empty
> set of N sub-objects of type T."
>
> and
>
> 5.3.3/2
> "When applied to an array, the result [of the sizeof operator] is the
> total number of bytes in the array. This implies that the size of an
> array of n elements is n times the size of an element."
>

Yep.  This is the operative wording.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: James Kuyper <kuyper@wizard.net>
Date: Tue, 12 Dec 2000 14:39:04 GMT
Raw View
Josh Sebastian wrote:
>
> I've been told that the Standard does not guarantee that elements of
> multidimensional arrays occupy contiguous memory. But the way I read
> the Standard, they must.

That's incorrect. What is correct, is that you can't safely move a
pointer outside the valid range of the array that it's a part of, even
if that array is itself a part of a larger array, in which case it would
be guaranteed contiguous.

> For example, given:
> int array[10][10];
>
> Is the following true?
> &array[x][0] == &array[0][0] + 10 * x; // 0<=x<10

Almost. The thing that governs the pointer &array[0][0] is array[0], not
array itself. Adding 10*x to that pointer would move that pointer
outside the valid range for array[0]. It's legal for a implementation to
fail (for instance by halting your program) when evaluating
&array[0][0]+n for any n<0 or n>10. Furthermore, it would be legal for
it to fail when evaluting *(&array[0][0]+n) for any n<0 or n>=10. The
difference in the upper limits is deliberate. Such an implementation
could be useful for debugging purposes, though it would probably be
unacceptably slow for actual production code.

However, the following statements are guaranteed true:

 &array[x] == &array[0] + x; // 0<=x && x<=10
 sizeof(array[0]) == 10u*sizeof(array[0][0]);

Section 3.9 says that any object of a POD type can be copied to an array
of sizof(object) 'char' or 'unsigned char' elements and back again,
preserving it's value. The text could be read as endorsing only copies
using std::memcpy(), but that certainly wasn't the intent. If the copy
is done by an explicit loop, then an implementation that used run-time
range checking on (char *) pointers based upon sub-array sizes would be
nonconforming. Therefore, the following should also be true:

(unsigned char *)(&array[x][0]) ==
 (unsigned char *)(&array[x][0])+10u*sizeof(int)*x;

> In particular, I have been told that an implementation is permitted to
> pad between the subarrays, so that array[x] + 10 != array[x+1] (where
> 0<=x<9).

False.

...

> So am I right?

Yes

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Josh Sebastian <curien@earthlink.net>
Date: Sun, 10 Dec 2000 20:53:54 GMT
Raw View
I've been told that the Standard does not guarantee that elements of
multidimensional arrays occupy contiguous memory. But the way I read
the Standard, they must.

For example, given:
int array[10][10];

Is the following true?
&array[x][0] == &array[0][0] + 10 * x; // 0<=x<10

In particular, I have been told that an implementation is permitted to
pad between the subarrays, so that array[x] + 10 != array[x+1] (where
0<=x<9).

The parts of the Standard that I'm looking at are

8.3.4/1
"An object of array type contains a contiguously allocated non-empty
set of N sub-objects of type T."

and

5.3.3/2
"When applied to an array, the result [of the sizeof operator] is the
total number of bytes in the array. This implies that the size of an
array of n elements is n times the size of an element."

It seems to me that 5.3.3/2 prevents any "padding" of the subarrays
because sizeof(array) must be 10 * sizeof(array[0]). And
sizeof(array[0]) must be 10 * sizeof(array[0][0]), which is 10 *
sizeof(int). So sizeof(array) _must_be_ 100 * sizeof(int), which
leaves no room for padding.

So am I right?
_______

"Yields falsehood when preceded by its quotation" yields falsehood when preceded by its quotation.

Josh Sebastian
<curien@earthlink.net>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]