Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Observable end padding in arrays

181 views
Skip to first unread message

Chris Vine

unread,
Jun 29, 2020, 4:49:35 PM6/29/20
to
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

unread,
Jun 29, 2020, 4:53:26 PM6/29/20
to
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

unread,
Jun 29, 2020, 4:55:54 PM6/29/20
to
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

unread,
Jun 29, 2020, 5:04:46 PM6/29/20
to
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

unread,
Jun 29, 2020, 5:08:24 PM6/29/20
to
On 29.06.2020 22:53, Vir Campestris wrote:
> On 29/06/2020 21:49, Chris Vine wrote:
>>
>> [snip]
>> 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.

Surely you mean the opposite?


> 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.

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

unread,
Jun 29, 2020, 5:15:17 PM6/29/20
to
That is indeed what I was looking for. Many thanks.

Keith Thompson

unread,
Jun 29, 2020, 5:18:55 PM6/29/20
to
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.T...@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Chris Vine

unread,
Jun 29, 2020, 5:38:19 PM6/29/20
to
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

unread,
Jun 29, 2020, 5:41:15 PM6/29/20
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
[...]
>> On 29/06/2020 21:49, Chris Vine wrote:
[...]
>>> 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.

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.)

Juha Nieminen

unread,
Jun 30, 2020, 2:20:57 AM6/30/20
to
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> 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?

Not an answer to your question, but it reminded me of a conversation I had
recently about why there is no multidimensional version of std::array.

Why should there be? Because, AFAIK, std::array<std::array<T, X>, Y> is not
guaranteed to be contiguous.

Chris Vine

unread,
Jun 30, 2020, 6:39:58 AM6/30/20
to
On Mon, 29 Jun 2020 14:41:07 -0700
Keith Thompson <Keith.S.T...@gmail.com> wrote:
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
> [...]
> >> On 29/06/2020 21:49, Chris Vine wrote:
> [...]
> >>> 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.
>
> 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.)

It is odd, which is maybe why I missed it.

The first sentence of the text extracted by Alf ("When applied to an
array, the result is the total number of bytes in the array") is a
truism, arising from the specification for the sizeof operator itself
in §8.3.3/1: "The sizeof operator yields the number of bytes in the
object representation of its operand".

So the "this implies ..." is not implied at all. It does however appear
to be normative, which is good enough for me. (At least, until the C++
standard committee notice this infelicity in the standard and decide to
resolve it by removing the requirement for no end padding. Removing
that requirement would break some pre-existing code concerning the
accessing of elements of multi-dimensional arrays, but that has not
dissuaded the committee before with their changes to object lifetime
rules.)

Vir Campestris

unread,
Jun 30, 2020, 6:28:59 PM6/30/20
to
On 29/06/2020 22:08, Alf P. Steinbach wrote:
> On 29.06.2020 22:53, Vir Campestris wrote:
>> On 29/06/2020 21:49, Chris Vine wrote:
>>>
>>> [snip]
>>> 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.
>
> Surely you mean the opposite?

The bit I meant you snipped "may not have observable end padding".

Andy

red floyd

unread,
Jul 1, 2020, 12:12:53 AM7/1/20
to
Why?

Tim Rentsch

unread,
Jul 6, 2020, 9:26:59 AM7/6/20
to
Surely the intention is that sizeof (std::array<T,N>) == sizeof (T[N])
(that is, there is no padding, and both are equal to N * sizeof (T)).
If the text of the Standard doesn't convey that clearly then the
property might deserve being addressed explicitly, but is there any
question that the intention is for std::array<T,N> to be just the
elements and nothing else (and in particular, no padding)?

Öö Tiib

unread,
Jul 6, 2020, 11:47:59 AM7/6/20
to
I can't find anything in standard that forbids compiler to add something
after the array in the aggregate struct (that std::array is). My skills
to guess intentions of other people have been always worse than my
searching skills ... so I would indeed like that intention (if it
exists) to be expressed bit more obviously.


James Kuyper

unread,
Jul 6, 2020, 11:48:30 AM7/6/20
to
As usual, I'm more concerned about what the committee actually wrote,
not what it intended to write (though the intent should certainly be
taken into consideration when determining how any failure to correctly
convey the intent should be corrected). The relevant words for
std::array are:

"An array is a contiguous container (26.2.1)." (26.3.7.1p1)

"A contiguous container is a container that supports random access
iterators (27.2.7) and whose member types iterator and const_iterator
are contiguous iterators (27.2.1)." (27.2.1p13)

"Iterators that further satisfy the requirement that, for integral
values n and dereferenceable iterator values a and (a + n), *(a + n) is
equivalent to *(addressof(*a) + n), are called contiguous iterators."
(27.2.1p6)

That text rules out padding between elements, but does not prohibit a
std::array<T> object from containing other things in addition to the
individual elements of the array, either before or after the elements,
possibly including padding. Unlike you, I see no reason to assume that
the failure to address such possibilities was unintentional.

Alf P. Steinbach

unread,
Jul 6, 2020, 2:44:51 PM7/6/20
to
The original Boost implementation was a simple `struct`, an aggregate,
to support C++03 curly braces initialization.

That didn't formally prevent compilers from adding padding, but modern
compilers do not add padding needlessly.

As I recall the question of whether `struct{ char x; }` is practically
guaranteed to be of size 1 has been discussed many times (though perhaps
not in this group), and the answer has always been yes, with current
compilers. However it's not formally guaranteed. And with the
committee's focus on standardizing new features instead of established
practice, I guess there will never be a standard `#pragma pack`, or
equivalent attribute which would be more ideal, perhaps.


- Alf

Juha Nieminen

unread,
Jul 6, 2020, 5:32:50 PM7/6/20
to
red floyd <no....@its.invalid> wrote:
>> Why should there be? Because, AFAIK, std::array<std::array<T, X>, Y> is not
>> guaranteed to be contiguous.
>>
> Why?

If you have something like

struct S { char data[5]; };

is something like

S table[100];

guaranteed to be exactly 500 bytes in size?

Juha Nieminen

unread,
Jul 6, 2020, 5:35:51 PM7/6/20
to
James Kuyper <james...@alumni.caltech.edu> wrote:
> As usual, I'm more concerned about what the committee actually wrote,
> not what it intended to write (though the intent should certainly be
> taken into consideration when determining how any failure to correctly
> convey the intent should be corrected). The relevant words for
> std::array are:
>
> "An array is a contiguous container (26.2.1)." (26.3.7.1p1)
>
> "A contiguous container is a container that supports random access
> iterators (27.2.7) and whose member types iterator and const_iterator
> are contiguous iterators (27.2.1)." (27.2.1p13)
>
> "Iterators that further satisfy the requirement that, for integral
> values n and dereferenceable iterator values a and (a + n), *(a + n) is
> equivalent to *(addressof(*a) + n), are called contiguous iterators."
> (27.2.1p6)
>
> That text rules out padding between elements, but does not prohibit a
> std::array<T> object from containing other things in addition to the
> individual elements of the array, either before or after the elements,
> possibly including padding. Unlike you, I see no reason to assume that
> the failure to address such possibilities was unintentional.

The problem I see is not that there would be padding between
array elements, but that there may well be padding at the end of
a struct. In other words, if you have like

struct S { char data[5]; }

S table[100];

is 'table' guaranteed to be 500 bytes in size? Is it guaranteed
that there will be no padding at the end of that struct?

(I genuinely don't know.)

red floyd

unread,
Jul 6, 2020, 6:02:03 PM7/6/20
to
No, because S itself is not guaranteed to be exactly 5 bytes.

However, table is guaranteed to be 100 * sizeof(S)

Chris M. Thomasson

unread,
Jul 6, 2020, 6:17:04 PM7/6/20
to
Agreed. One can represent n-ary arrays in a 1d array. Humm... Is the
placement new array form basically useless because the program does not
know the one "true" size? If the implementation adds in any extra meta
data, such as how many dtors to call when the array form of delete is
used, then the size of the user provided buffer will not be sufficient?

Paavo Helde

unread,
Jul 6, 2020, 6:33:54 PM7/6/20
to
07.07.2020 00:35 Juha Nieminen kirjutas:
> The problem I see is not that there would be padding between
> array elements, but that there may well be padding at the end of
> a struct. In other words, if you have like
>
> struct S { char data[5]; }
>
> S table[100];
>
> is 'table' guaranteed to be 500 bytes in size? Is it guaranteed
> that there will be no padding at the end of that struct?

No, of course not. An implementation can easily decide that such a
struct is most effectively accessed when aligned on a 8-byte border, for
example. In this case sizeof(S) would be 8.

I guess the same applies for nested std::arrays. If you want a
contiguous array with linear indexing, allocate a single continuous
array; if you want multidimensional indexing, allocate a nested
multidimensional array. It's as simple as that.

Tim Rentsch

unread,
Jul 6, 2020, 10:21:16 PM7/6/20
to
Keith Thompson <Keith.S.T...@gmail.com> writes:

> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
> [...]
>
>>> On 29/06/2020 21:49, Chris Vine wrote:
>
> [...]
>
>>>> 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.
>
> 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. [...]

The C++ standard uses but does not define the term "array type".

The C++ standard includes the C standard as a normative reference
(1 p2, "C++ is a general purpose programming language based on
the C programming language as described in ISO/IEC 9899:2011
Programming languages - C", and also 2 p1.3).

The C standard defines the term "array type" - 6.2.5 p20, first
subitem: "An array type describes a contiguously allocated
nonempty set of objects with a particular member object type,
called the element type" (and "array type" is italicized,
indicating a definition).

An array type under the C definition has no padding.

So unless there is a conflicting statement somewhere in the C++
standard, it seems reasonable to conclude arrays in C++ cannot
have padding.

Alf P. Steinbach

unread,
Jul 6, 2020, 11:14:33 PM7/6/20
to
That's not implied by your quote.

Which C standard is the quote from, anyway?


> So unless there is a conflicting statement somewhere in the C++
> standard, it seems reasonable to conclude arrays in C++ cannot
> have padding.

Yes, but first one has to prove the C case.


- Alf

Juha Nieminen

unread,
Jul 7, 2020, 2:24:52 AM7/7/20
to
That's why std::array<std::array<T, X>, Y> is not guaranteed to be
contiguous, which makes it different from a two-dimensional array.
Ie. the answer to your question.

Juha Nieminen

unread,
Jul 7, 2020, 2:27:02 AM7/7/20
to
Hence why we need a multidimensional version of std::array, because

Keith Thompson

unread,
Jul 7, 2020, 2:37:26 AM7/7/20
to
Tim Rentsch <tr.1...@z991.linuxsc.com> writes:
> Keith Thompson <Keith.S.T...@gmail.com> writes:
>
>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>> [...]
>>
>>>> On 29/06/2020 21:49, Chris Vine wrote:
>>
>> [...]
>>
>>>>> 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.
>>
>> 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. [...]
>
> The C++ standard uses but does not define the term "array type".

The C++ standard doesn't define that particular phrase, but it discusses
array types in 6.9.2 [basic.compound] and 11.3.4 [dcl.array] (references
are to C++17).

> The C++ standard includes the C standard as a normative reference
> (1 p2, "C++ is a general purpose programming language based on
> the C programming language as described in ISO/IEC 9899:2011
> Programming languages - C", and also 2 p1.3).
>
> The C standard defines the term "array type" - 6.2.5 p20, first
> subitem: "An array type describes a contiguously allocated
> nonempty set of objects with a particular member object type,
> called the element type" (and "array type" is italicized,
> indicating a definition).

C++17 11.3.4: "An object of array type contains a contiguously allocated
non-empty set of N subobjects of type T."

> An array type under the C definition has no padding.
>
> So unless there is a conflicting statement somewhere in the C++
> standard, it seems reasonable to conclude arrays in C++ cannot
> have padding.

The C++ standard includes (most of) the C library by reference, but as I
understand it it provides its own descriptions of everything in the core
language. I'm not aware of anything in the C++ core language that's
defined by the C standard. At the very least, *most* of the C++ core
language is defined directly by the C++ standard. If there are
omissions, my first assumption would be that they're unintentional, not
that the C core language definition fills in the gaps.

It's not 100% clear to me that either the C or C++ discussion of array
types completely excludes the possibility of padding at the end.

James Kuyper

unread,
Jul 7, 2020, 9:57:15 AM7/7/20
to
On 7/6/20 11:14 PM, Alf P. Steinbach wrote:
> On 07.07.2020 04:21, Tim Rentsch wrote:
...
>> The C++ standard includes the C standard as a normative reference
>> (1 p2, "C++ is a general purpose programming language based on
>> the C programming language as described in ISO/IEC 9899:2011
^^^^
>> Programming languages - C", and also 2 p1.3).
>>
>> The C standard defines the term "array type" - 6.2.5 p20, first
>> subitem: "An array type describes a contiguously allocated
>> nonempty set of objects with a particular member object type,
>> called the element type" (and "array type" is italicized,
>> indicating a definition).
>>
>> An array type under the C definition has no padding.
>
> That's not implied by your quote.

If an array type in C were allowed to include padding, then the above
quote would have to mention the padding as part of what an array type
describes.

> Which C standard is the quote from, anyway?

He explicitly specified that he was quoting from ISO/IEC 9899:2011.

All versions of the C standard have said essentially the same thing
about that matter.

Manfred

unread,
Jul 7, 2020, 10:30:44 AM7/7/20
to
On 7/7/2020 3:57 PM, James Kuyper wrote:
> On 7/6/20 11:14 PM, Alf P. Steinbach wrote:
>> On 07.07.2020 04:21, Tim Rentsch wrote:
> ...
>>> The C++ standard includes the C standard as a normative reference
>>> (1 p2, "C++ is a general purpose programming language based on
>>> the C programming language as described in ISO/IEC 9899:2011
> ^^^^
>>> Programming languages - C", and also 2 p1.3).
>>>
>>> The C standard defines the term "array type" - 6.2.5 p20, first
>>> subitem: "An array type describes a contiguously allocated
>>> nonempty set of objects with a particular member object type,
>>> called the element type" (and "array type" is italicized,
>>> indicating a definition).
>>>
>>> An array type under the C definition has no padding.
>>
>> That's not implied by your quote.
>
> If an array type in C were allowed to include padding, then the above
> quote would have to mention the padding as part of what an array type
> describes.

Not really, for example the following definition about structure type
does not mention padding either, but we know that padding may very well
exist there.
The difference between array and structure is that the former uses the
term "contiguously", and the latter uses "sequentially".
This makes clear that no padding is allowed /between/ elements of an
array, but to me it does not explicitly state that no extra allocated
space is allowed at the /end/ of the array, although this may well
follow from some other statement in the C standard.

Chris M. Thomasson

unread,
Jul 7, 2020, 3:07:21 PM7/7/20
to
Humm... I would not mind a multidimensional version of std::array.

James Kuyper

unread,
Jul 7, 2020, 3:29:12 PM7/7/20
to
On 7/7/20 10:30 AM, Manfred wrote:
> On 7/7/2020 3:57 PM, James Kuyper wrote:
>> On 7/6/20 11:14 PM, Alf P. Steinbach wrote:
>>> On 07.07.2020 04:21, Tim Rentsch wrote:
>> ...
>>>> The C++ standard includes the C standard as a normative reference
>>>> (1 p2, "C++ is a general purpose programming language based on
>>>> the C programming language as described in ISO/IEC 9899:2011
>> ^^^^
>>>> Programming languages - C", and also 2 p1.3).
>>>>
>>>> The C standard defines the term "array type" - 6.2.5 p20, first
>>>> subitem: "An array type describes a contiguously allocated
>>>> nonempty set of objects with a particular member object type,
>>>> called the element type" (and "array type" is italicized,
>>>> indicating a definition).
>>>>
>>>> An array type under the C definition has no padding.
>>>
>>> That's not implied by your quote.
>>
>> If an array type in C were allowed to include padding, then the above
>> quote would have to mention the padding as part of what an array type
>> describes.
>
> Not really, for example the following definition about structure type
> does not mention padding either, but we know that padding may very well
> exist there.

Yes, we know it because it's explicitly specified that "There may be
unnamed padding within a structure object, but not at its beginning."
(6.7.2.1p15) and "There may be unnamed padding at the end of a structure
or union." (6.7.2.1p17). There are no such statements for arrays.

The existence of an exception implies the existence of a rule that it is
an exception to. The fact that there need to be explicit statements that
padding is permitted between the members of a struct and at the end
implies that such padding is not permitted for arrays, for which no such
exceptions have been specified.

Alf P. Steinbach

unread,
Jul 7, 2020, 7:03:40 PM7/7/20
to
On 07.07.2020 08:37, Keith Thompson wrote:
>
> The C++ standard includes (most of) the C library by reference, but as I
> understand it it provides its own descriptions of everything in the core
> language. I'm not aware of anything in the C++ core language that's
> defined by the C standard.

Minimum ranges of integer types.


> At the very least, *most* of the C++ core
> language is defined directly by the C++ standard. If there are
> omissions, my first assumption would be that they're unintentional, not
> that the C core language definition fills in the gaps.
>
> It's not 100% clear to me that either the C or C++ discussion of array
> types completely excludes the possibility of padding at the end.

For the C++ standard it's explicitly stated in normative text, but
implicitly referring to some other unspecified text via "this implies".

It was the same with the UB of dereferencing a nullpointer, a reference
to other text that was nowhere to be found. On the contrary, the only
text that clearly was about that, was a statement that it was /not/ UB
in a `typeid` expression. I believe there was an attempt to fix this in
C++11 but as I recall they didn't manage to clear it up completely,
although that would not be hard to do -- which IMHO on its own brings
the competence of the committee into question. Then later we got UTF-8
character literals and `std::byte` and the C++20 sabotage of UTF-8 from
`std::filesystem::path` and silly support of compiler internals like
optimization of successive `new`-expressions, and such, not to mention
continuations misleadingly called coroutines and without the necessary
library support for the very Microsoftic base functionality. It's scary.

- Alf

Keith Thompson

unread,
Jul 7, 2020, 7:53:33 PM7/7/20
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
> On 07.07.2020 08:37, Keith Thompson wrote:
>> The C++ standard includes (most of) the C library by reference, but as I
>> understand it it provides its own descriptions of everything in the core
>> language. I'm not aware of anything in the C++ core language that's
>> defined by the C standard.
>
> Minimum ranges of integer types.

Fair enough -- though that's also an example of inheriting the contents
of <limits.h> from the C library.

>> At the very least, *most* of the C++ core
>> language is defined directly by the C++ standard. If there are
>> omissions, my first assumption would be that they're unintentional, not
>> that the C core language definition fills in the gaps.
>>
>> It's not 100% clear to me that either the C or C++ discussion of array
>> types completely excludes the possibility of padding at the end.
>
> For the C++ standard it's explicitly stated in normative text, but
> implicitly referring to some other unspecified text via "this
> implies".

Right, and I'm trying to figure out what the "this implies" refers to.

> It was the same with the UB of dereferencing a nullpointer, a
> reference to other text that was nowhere to be found. On the contrary,
> the only text that clearly was about that, was a statement that it was
> /not/ UB in a `typeid` expression. I believe there was an attempt to
> fix this in C++11 but as I recall they didn't manage to clear it up
> completely, although that would not be hard to do -- which IMHO on its
> own brings the competence of the committee into question.

Hmm. C++17 8.3.1 [expr.unary.op] :
The unary * operator performs indirection: the expression to which
it is applied shall be a pointer to an object type, or a pointer to
a function type and the result is an lvalue referring to the object
or function to which the expression points.
C++11 has similar or identical wording. This defines the behavior when
there is such an object or function. By failing to define the behavior
when there is no such object or function, it leave the behavior
undefined by omission. A note under the definition of undefined
behavior (3.27 [defns.undefined]):
Undefined behavior may be expected when this document omits any
explicit definition of behavior or when a program uses an erroneous
construct or erroneous data.

I wouldn't mind if the standard were a bit more explicit about
dereferencing a null pointer (or any other pointer that doesn't
point to an object or function), but it seems unambiguous as it is.
My only complaint might be that the wording assumes that the object
or function exists rather than saying what happens *if* it exists.

[snip]

My guess is that the authors of the standard thought it was so obvious
that arrays can't have padding at the end that they didn't bother to
state it.

Manfred

unread,
Jul 8, 2020, 7:43:14 AM7/8/20
to
Which is "some other statement in the C standard" like I mentioned in my
previous post.

>
> The existence of an exception implies the existence of a rule that it is
> an exception to. The fact that there need to be explicit statements that
> padding is permitted between the members of a struct and at the end
> implies that such padding is not permitted for arrays, for which no such
> exceptions have been specified.
>

I understand your point, however this would assume a very high level of
self-consistency of the standard, a level that I am not 100% confident I
can acknowledge. That said, I tend to consider the C standard somewhat
more solid than the C++ one.

Somehow related to your position (an exception implies a rule even if
the rule is missing), the approach of the C++ standard according to
which "Undefined behavior may be expected when this document omits any
explicit definition of behavior..." puts a lot of responsibility on the
standard committee, probably too much given how controversial the UB
topic has become.
Expecially given the meaning of UB when it comes to compilers: it is a
very well-defined Bad Thing™.

James Kuyper

unread,
Jul 8, 2020, 10:37:40 AM7/8/20
to
On 7/8/20 7:43 AM, Manfred wrote:
> On 7/7/2020 9:29 PM, James Kuyper wrote:
>> On 7/7/20 10:30 AM, Manfred wrote:
>>> On 7/7/2020 3:57 PM, James Kuyper wrote:
>>>> On 7/6/20 11:14 PM, Alf P. Steinbach wrote:
>>>>> On 07.07.2020 04:21, Tim Rentsch wrote:
...
>>>>>> The C standard defines the term "array type" - 6.2.5 p20, first
>>>>>> subitem: "An array type describes a contiguously allocated
>>>>>> nonempty set of objects with a particular member object type,
>>>>>> called the element type" (and "array type" is italicized,
>>>>>> indicating a definition).
>>>>>>
>>>>>> An array type under the C definition has no padding.
>>>>>
>>>>> That's not implied by your quote.
>>>>
>>>> If an array type in C were allowed to include padding, then the above
>>>> quote would have to mention the padding as part of what an array type
>>>> describes.
>>>
>>> Not really, for example the following definition about structure type
>>> does not mention padding either, but we know that padding may very well
>>> exist there.
>>
>> Yes, we know it because it's explicitly specified that "There may be
>> unnamed padding within a structure object, but not at its beginning."
>> (6.7.2.1p15) and "There may be unnamed padding at the end of a structure
>> or union." (6.7.2.1p17). There are no such statements for arrays.
>
> Which is "some other statement in the C standard" like I mentioned in my
> previous post.

Yes, but your wording "this may well follow from" implied uncertainty
about the existence of that other statement, uncertainty which I hope
I've removed.

>> The existence of an exception implies the existence of a rule that it is
>> an exception to. The fact that there need to be explicit statements that
>> padding is permitted between the members of a struct and at the end
>> implies that such padding is not permitted for arrays, for which no such
>> exceptions have been specified.
>>
>
> I understand your point, however this would assume a very high level of
> self-consistency of the standard, a level that I am not 100% confident I
> can acknowledge. That said, I tend to consider the C standard somewhat
> more solid than the C++ one.
>
> Somehow related to your position (an exception implies a rule even if
> the rule is missing), ...

While that is true in general, the rule should not actually be missing
in this case - if it were, that would constitute a defect in the
standard. I argue that the rule is actually present as an implication of
the "An array type describes ..." clause, for precisely the reasons I
gave in my original post. It's merely inobvious and correspondingly
debatable. The existence of an exception provides evidence in support of
my side in that debate; but if I were wrong in my interpretation of the
"describes" clause, then the exception would not make me right.

Tim Rentsch

unread,
Jul 9, 2020, 8:47:30 AM7/9/20
to
As I read the C standard, it is. My reasoning is pretty much the
same as that given by James Kuyper.

> Which C standard is the quote from, anyway?

C 2011, the same as what was mentioned in the normative reference.
(I should add that technically my quote came from the pre-standard
draft rather than the official standard, but I believe the wording
is the same in both documents.)

>> So unless there is a conflicting statement somewhere in the C++
>> standard, it seems reasonable to conclude arrays in C++ cannot
>> have padding.
>
> Yes, but first one has to prove the C case.

It has been established to my satisfaction. You are free to draw
a different conclusion if that's what you would like to do.

Tim Rentsch

unread,
Jul 9, 2020, 10:05:07 AM7/9/20
to
Keith Thompson <Keith.S.T...@gmail.com> writes:

> Tim Rentsch <tr.1...@z991.linuxsc.com> writes:
>
>> Keith Thompson <Keith.S.T...@gmail.com> writes:
>>
>>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>>> [...]
>>>
>>>>> On 29/06/2020 21:49, Chris Vine wrote:
>>>
>>> [...]
>>>
>>>>>> 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.
>>>
>>> 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. [...]
>>
>> The C++ standard uses but does not define the term "array type".
>
> The C++ standard doesn't define that particular phrase, but it discusses
> array types in 6.9.2 [basic.compound] and 11.3.4 [dcl.array] (references
> are to C++17).

I hadn't noticed the passage in 6.9.2; thank you for pointing it
out.

The references to array type in 11.3.4 are ones I had seen as part
of my review prior to the earlier posting. These passages do refer
to "array type"; I don't think either one is meant to define the
term, only to refer to it.

>> The C++ standard includes the C standard as a normative reference
>> (1 p2, "C++ is a general purpose programming language based on
>> the C programming language as described in ISO/IEC 9899:2011
>> Programming languages - C", and also 2 p1.3).
>>
>> The C standard defines the term "array type" - 6.2.5 p20, first
>> subitem: "An array type describes a contiguously allocated
>> nonempty set of objects with a particular member object type,
>> called the element type" (and "array type" is italicized,
>> indicating a definition).
>
> C++17 11.3.4: "An object of array type contains a contiguously
> allocated non-empty set of N subobjects of type T."

That sentence states a property of objects (of array type) but
doesn't define the term "array type" itself. For that matter it
isn't a definition of array-type objects either: it says they
/contain/ "a contiguously allocated non-empty set of N subobjects"
but doesn't say what else might be true (or not) about them.

>> An array type under the C definition has no padding.
>>
>> So unless there is a conflicting statement somewhere in the C++
>> standard, it seems reasonable to conclude arrays in C++ cannot
>> have padding.
>
> The C++ standard includes (most of) the C library by reference,
> but as I understand it it provides its own descriptions of
> everything in the core language.

The second paragraph of section 1 (intro.scope) says this:

C++ is a general purpose programming language based on the C
programming language as described in ISO/IEC 9899:2011
Programming languages -- C (hereinafter referred to as the C
standard). In addition to the facilities provided by C, C++
provides additional data types, classes, templates,
exceptions, namespaces, operator overloading, function name
overloading, references, free store management operators,
and additional library facilities.

> I'm not aware of anything in the C++ core language that's defined by
> the C standard. At the very least, *most* of the C++ core language
> is defined directly by the C++ standard. If there are omissions, my
> first assumption would be that they're unintentional, not that the C
> core language definition fills in the gaps.

That assumption may very well be right. I do think though that the
existing wording can be read either way. The quoted 1 p2 does say
"In addition to the facilities /provided/ by C" (my emphasis). If
we can agree that either interpretation is at least plausible then
I am happy to leave it at that.

> It's not 100% clear to me that either the C or C++ discussion of array
> types completely excludes the possibility of padding at the end.

As far as C goes, I consider it a settled question. My reasoning
is much the same as what James Kuyper said in his followups to
Alf and Manfred: the definition of "array type" doesn't consider
the possibility of anything other than a contiguously allocated
set of objects, and other derived types that do admit padding
all mention padding explicitly.

Also, if it helps, I asked about this question many years ago in
comp.lang.c (or maybe comp.std.c?). There was a response from Doug
Gwyn, who said array types cannot have padding (or words to that
effect). I'm sorry I can't be more specific; it was a long time
ago, and the groups history seems to have fallen off the face of
the earth. IIRC 'sizeof (T[N]) == N * sizeof (T)' was included
in the subject line. If some ambitious web searcher is able to
find something about those it would be nice to hear about it.

Tim Rentsch

unread,
Jul 10, 2020, 10:43:48 AM7/10/20
to
Keith Thompson <Keith.S.T...@gmail.com> writes:

> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

<snip>
To me it looks like the wording here (for C++) is carelessly
chosen. The wording used (about unary *) in the C standard is
decidedly better.

> [snip]
>
> My guess is that the authors of the standard thought it was so obvious
> that arrays can't have padding at the end that they didn't bother to
> state it.

In the case of C, there is a strong case that the definition
simply doesn't admit anything, whether padding or anything else,
other than the array elements themselves. If that is true then
it doesn't matter whether it's obvious or not - the definition
given precludes the possibility of padding without needing to
say so explicitly.

In the case of C++, if the intention was to rely on the C
standard for the definition of array type then again there no
need to appeal to obviousness. If however the intention in the
C++ standard was to stand on its own (in particular, for this
aspect - there are other cases where reliance on the C standard
is stated explicitly), then the wording in the C++ standard
comes up short, and merits being revised to make the description
less ambiguous.

The above remarks includes in some respects my opinions on
meaning and writing quality, in case that needs saying.

Tim Rentsch

unread,
Aug 23, 2020, 6:13:18 AM8/23/20
to
I second your vote that the properties intended be expressed more
obviously. Also please note that my comment was not making an
assertion but rather was asking a question.

Tim Rentsch

unread,
Aug 23, 2020, 9:31:46 AM8/23/20
to
James Kuyper <james...@alumni.caltech.edu> writes:

> On Monday, July 6, 2020 at 9:26:59 AM UTC-4, Tim Rentsch wrote:
>
>> Juha Nieminen <nos...@thanks.invalid> writes:
>>
>>> Chris Vine <chris@cvine--nospam--.freeserve.co.uk> 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?
>>>
>>> Not an answer to your question, but it reminded me of a conversation
>>> I had recently about why there is no multidimensional version of
>>> std::array.
>>>
>>> Why should there be? Because, AFAIK, std::array<std::array<T, X>, Y>
>>> is not guaranteed to be contiguous.
>>
>> Surely the intention is that sizeof (std::array<T,N>) == sizeof (T[N])
>> (that is, there is no padding, and both are equal to N * sizeof (T)).
>> If the text of the Standard doesn't convey that clearly then the
>> property might deserve being addressed explicitly, but is there any
>> question that the intention is for std::array<T,N> to be just the
>> elements and nothing else (and in particular, no padding)?
>
> As usual, I'm more concerned about what the committee actually wrote,
> not what it intended to write [...]

I'm afraid you have misunderstood the distinction I refer to. It
seems reasonable to assume the words that appear in the standards
reflect what words the respective committees expect and intend to
appear. The question is not what /words/ are intended but what
/meaning/ is intended. A given sequence of words and sentences
doesn't always convey a single meaning, nor necessarily the same
meaning to different readers. The question of what meaning is
intended is paramount.
0 new messages