Monday, June 29, 2020

Digest for comp.lang.c++@googlegroups.com - 11 updates in 3 topics

raltbos@xs4all.nl (Richard Bos): Jun 29 09:58PM

> @Bqv~~o?gx|\<wI!SXOV:^]q+sIjeyi(<H{K-KWm"x/t
> a?<lk?hp?+xtTB,JdG\pU9O'vvFw=d(*7P?i4cW{AYYB
> 1,DCxI8=kU:db\F;*r^9!6hpo,"0#Ja(XK&|+4G(X@N#
 
You can't fool me. That's not Befunge. This is:
 
"'.niagA kcaB d"v> v
v$<v"r There an"< >$v
>#| :,: |#<
@>"o ,egnufeB'"^@
 
Richard
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 29 09:49PM +0100

Hi,
 
I have been trying to prove to myself that, under the C++ standard,
one-dimensional arrays may not have observable end padding. It is clear
that the elements of an array must be contiguous, in the sense that for
an array of T of more than one element, &T[1] must be the same as
&T[0]+sizeof(T), and so on, but I have not yet managed to find a
provision which unambiguously forbids array end padding.
 
In other words I have not found a requirement that, for any type T,
sizeof(T[sz]) must be the same as sizeof(T)*sz.
 
Where you might care about this is in relation to matrices (and other
multi-dimensional arrays), where the issue translates into the extent to
which you are allowed to use pointer arithmetic to access individual
elements in matrices instead of using the subscript operators.
 
I have seen lots of code which assumes contiguity over the whole of a
multi-dimensional array, and I am pretty certain this requirement
exists, but can anyone point me to where I can find it?
Vir Campestris <vir.campestris@invalid.invalid>: Jun 29 09:53PM +0100

On 29/06/2020 21:49, Chris Vine wrote:
 
> I have seen lots of code which assumes contiguity over the whole of a
> multi-dimensional array, and I am pretty certain this requirement
> exists, but can anyone point me to where I can find it?
 
I think if there was such a requirement every compiler I've ever used
would disobey it.
 
Just the way all the libraries pad malloc (etc) requests up to some
suitable block size.
 
If I have an on-stack int64_t, then an array char[5], then another
int64_t I'd be astonished to find there wasn't a gap at the end of the
array.
 
Andy
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 29 01:55PM -0700

On 6/29/2020 1:49 PM, Chris Vine wrote:
 
> I have seen lots of code which assumes contiguity over the whole of a
> multi-dimensional array, and I am pretty certain this requirement
> exists, but can anyone point me to where I can find it?
 
Fwiw, I always liked using a one dimensional array, then partitioning it
using some math. Think of representing a 2d plane in a 1d array.
 
Using the array form of new seems to create an unseen header.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 29 10:04PM +0100

On Mon, 29 Jun 2020 21:53:16 +0100
 
> If I have an on-stack int64_t, then an array char[5], then another
> int64_t I'd be astonished to find there wasn't a gap at the end of the
> array.
 
Yes, I formulated my question poorly, as that was not my point about
"observable padding". My "observable" was in the context of
multi-dimensional arrays and the size of component sub-arrays. I would
bet that sizeof(char[5]) is indeed 5 with your compiler, and I would
like to prove that that is required.
 
Can you point me to something that says that, for any type T,
sizeof(T[sz]) must be the same as sizeof(T)*sz?
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 29 11:08PM +0200

On 29.06.2020 22:53, Vir Campestris wrote:
>> exists, but can anyone point me to where I can find it?
 
> I think if there was such a requirement every compiler I've ever used
> would disobey it.
 
Surely you mean the opposite?
 
 
 
> If I have an on-stack int64_t, then an array char[5], then another
> int64_t I'd be astonished to find there wasn't a gap at the end of the
> array.
 
That doesn't appear to be what Chris is talking about.
 
As I see it he's talking about
 
 
>> a requirement that, for any type T, sizeof(T[sz]) must be the same as
>> sizeof(T)*sz
 
In C++17 this is specified by §8.3.3/2,
 
❝When applied to an array, the result 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.❞
 
... where the ❝This implies❞ is normative text, not a note.
 
 
- Alf
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 29 10:15PM +0100

On Mon, 29 Jun 2020 23:08:13 +0200
> the array. This implies that the size of an array of /n/ elements is /n/
> times the size of an element.❞
 
> ... where the ❝This implies❞ is normative text, not a note.
 
That is indeed what I was looking for. Many thanks.
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Jun 29 02:18PM -0700


> If I have an on-stack int64_t, then an array char[5], then another
> int64_t I'd be astonished to find there wasn't a gap at the end of the
> array.
 
The question isn't about padding between distinct objects.
 
Given:
 
int64_t a;
char b[5];
int64_t c;
 
the standard says nothing about the order in which they're allocated.
For certain orders, some padding may be required to satisfy alignment
requirements. But even if they're allocated in the order in which
they're defined, any padding following b is not part of b; sizeof
(b) will (presumably) be 5, and the following 3(?) bytes will not
be part of any named object. (Or the compiler might allocate some
other object in that space.)
 
Every compiler I've seen has sizeof (b) == 5 (disclaimer: I haven't
really tested this). The question is whether the standard requires
this, or allows padding past 5 bytes to be *part of* the array object.
 
In a very quick look at (a draft of) the C++17 standard, I haven't found
an explicit requirement. Either such a requirement is there and I
haven't found it (always possible), or the authors of the standard felt
it was too obvious to state. (Or they intended to allow padding at the
end of an array, but I personally don't think that's likely.)
 
Note that we can't necessarily use multidimensional arrays to argue that
padding is forbidden. Given:
 
int arr[5][5]
 
the expression arr[0][7] has undefined behavior; it's not necessarily
equivalent to arr[1][2]. (Typical compilers may generate the same code
for both expression, which is of course valid for undefined behavior.)
 
However, arr[0][5] is a valid pointer value (dereferencing it has
undefined behavior), so another way to state the question is whether
(&arr[0][5] == &arr[1][0]) must be true. Again, it typically is, but
that doesn't prove that the standard requires it.
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 29 10:38PM +0100

On Mon, 29 Jun 2020 13:55:46 -0700
 
> Fwiw, I always liked using a one dimensional array, then partitioning it
> using some math. Think of representing a 2d plane in a 1d array.
 
> Using the array form of new seems to create an unseen header.
 
Yes, when using languages in which arrays are boxed types where you are
provided with what amounts to a pointer to garbage collected memory,
and the element type in use is unboxed, such as an integer, then for
multi-dimensional arrays you are almost driven to constructing a single
array and layering arithmetic on the indices over it in order to secure
contiguity and localization and so encourage vectorized instructions.
 
Much as I appreciate garbage collection, this is the kind of low level
stuff where C and C++ and their array syntax come out well.
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Jun 29 02:41PM -0700

"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
[...]
>> On 29/06/2020 21:49, Chris Vine wrote:
[...]
> the array. This implies that the size of an array of /n/ elements is
> /n/ times the size of an element.❞
 
> ... where the ❝This implies❞ is normative text, not a note.
 
Yes, I had somehow managed to miss that.
 
I'm still curious *how* it implies it. The "This implies that ..."
wording seems to indicate that it's a consequence of some normative
requirement elsewhere in the standard. (Nevertheless, I accept
that it's required.)
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 29 10:02PM +0200

On 29.06.2020 19:22, Paavo Helde wrote:
> }
 
> Now the Func() call gets officially discarded and Func can legally
> remain undefined.
 
Gah, where's the upvote button on this Usenet thing?
 
- Alf
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: