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

Strange compiler warning...

132 views
Skip to first unread message

TDH1978

unread,
Dec 31, 2020, 5:11:26 PM12/31/20
to
I have the following piece of code:

void clear_mac(uint8_t a[6])
{
*a++ = 0;
*a++ = 0;
*a++ = 0;
*a++ = 0;
*a++ = 0;
*a = 0;
}


This code compiled cleanly for the last 15 years. When I upgraded to
the latest gcc/g++ 10.2.1 compiler on Fedora 33, I got the following
warning:

warning: writing 16 bytes into a region of size 6 [-Wstringop-overflow=]


Does anyone know what the problem is? I tried using "0x00" instead of
"0", to no avail. What "16 bytes" is the compiler referring to?


Keith Thompson

unread,
Dec 31, 2020, 5:25:06 PM12/31/20
to
That's odd. I don't see the same warning with gcc 10.2.0 (built from
source) on Ubuntu with any argument for the -Wstringop-overflow= option.

There is no gcc 10.2.1 release (yet).

There *shouldn't* be a warning for that code. The int value 0 is
converted to uint8_t before being stored in *a, so it won't write past
the bounds of a 6-element array.

Can you show a complete self-contained source file that exhibits the
problem (what you posted won't compile because uint8_t is not defined),
along with the exact command line you used to compile it and the output
of "gcc --version"?

--
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 */

Ian Collins

unread,
Dec 31, 2020, 5:53:09 PM12/31/20
to
A compiler bug? Which build are you running? If it was a bug, it may
have been fixed already.

There is no warning with the latest Ubuntu release (10.2.0) or with the
latest snapshot (11.0.0 20201220).

--
Ian.


Jorgen Grahn

unread,
Jan 1, 2021, 4:59:54 AM1/1/21
to
On Thu, 2020-12-31, TDH1978 wrote:
> I have the following piece of code:
>
> void clear_mac(uint8_t a[6])
> {
> *a++ = 0;
> *a++ = 0;
> *a++ = 0;
> *a++ = 0;
> *a++ = 0;
> *a = 0;
> }

As an aside, a std::array<uint8_t, 6> would be a better choice for a
MAC address. If some API wants a C array, it's easy to write a
conversion function.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

spudisnot...@grumpysods.com

unread,
Jan 1, 2021, 5:34:13 AM1/1/21
to
On 1 Jan 2021 09:59:38 GMT
Jorgen Grahn <grahn...@snipabacken.se> wrote:
>On Thu, 2020-12-31, TDH1978 wrote:
>> I have the following piece of code:
>>
>> void clear_mac(uint8_t a[6])
>> {
>> *a++ = 0;
>> *a++ = 0;
>> *a++ = 0;
>> *a++ = 0;
>> *a++ = 0;
>> *a = 0;
>> }
>
>As an aside, a std::array<uint8_t, 6> would be a better choice for a

Why? A MAC is a fixed size which will never change. A C array is efficient and
does the job.


Hergen Lehmann

unread,
Jan 1, 2021, 6:30:20 AM1/1/21
to
Am 01.01.21 um 11:33 schrieb spudisnot...@grumpysods.com:

> Jorgen Grahn <grahn...@snipabacken.se> wrote:
>> As an aside, a std::array<uint8_t, 6> would be a better choice for a
>
> Why? A MAC is a fixed size which will never change. A C array is efficient and
> does the job.

std::array is fixed size, too, but provides strict type safety, provides
bounds checking and allows the use of the standard algorithms library.

The classic C syntax can not safely distinguish between an actual array
and a bare pointer, which might not point to an array of the appropriate
size in some special case missed by the developer.

Alf P. Steinbach

unread,
Jan 1, 2021, 8:19:59 AM1/1/21
to
On 01.01.2021 12:10, Hergen Lehmann wrote:
> Am 01.01.21 um 11:33 schrieb spudisnot...@grumpysods.com:
>
>> Jorgen Grahn <grahn...@snipabacken.se> wrote:
>>> As an aside, a std::array<uint8_t, 6> would be a better choice for a
>>
>> Why? A MAC is a fixed size which will never change. A C array is
>> efficient and
>> does the job.
>
> std::array is fixed size, too, but provides strict type safety, provides
> bounds checking and allows the use of the standard algorithms library.

The standard algorithms work nicely with raw arrays. `std::end(a)` gives
you an end iterator for the array whether `a` is `std::array` or a raw
array. But when `a` is a pointer one must usually calculate an end
pointer like `a+n`, which means that `std::array` is more /practical/.


> The classic C syntax can not safely distinguish between an actual array
> and a bare pointer, which might not point to an array of the appropriate
> size in some special case missed by the developer.

Additionally, `std::array` can be easily returned from a function.

- Alf

David Brown

unread,
Jan 1, 2021, 8:46:43 AM1/1/21
to
An alternative for C is to put the array in a struct:

typedef struct {
uint8_t d[6];
} mac_address_t;

That is better than using a std::array in C++, because it gives a name
to the type - and functions dealing with mac addresses can be restricted
to taking only mac address types. Putting the array into the struct
makes it a fixed size and type-safe.

(Of course, for C++ you would make it a class, and put a std::array in
the class instead of a C array.)

spudisnot...@grumpysods.com

unread,
Jan 1, 2021, 11:18:57 AM1/1/21
to
On Fri, 1 Jan 2021 12:10:31 +0100
Hergen Lehmann <hlehmann.e...@snafu.de> wrote:
>Am 01.01.21 um 11:33 schrieb spudisnot...@grumpysods.com:
>
>> Jorgen Grahn <grahn...@snipabacken.se> wrote:
>>> As an aside, a std::array<uint8_t, 6> would be a better choice for a
>>
>> Why? A MAC is a fixed size which will never change. A C array is efficient
>and
>> does the job.
>
>std::array is fixed size, too, but provides strict type safety, provides
>bounds checking and allows the use of the standard algorithms library.

If a piece of code is checking MAC addresses its probably very low level
and could be in a tight loop where performance matters. Constantly doing
bounds checking on a fixed size array in this situation is a waste of
CPU cycles and needlessly slows the program down.

>The classic C syntax can not safely distinguish between an actual array
>and a bare pointer, which might not point to an array of the appropriate
>size in some special case missed by the developer.

I doubt it would need to. I can't imagine you'd pass a MAC address to a
function that takes a generic pointer as input. It needs special attention.

Chris Vine

unread,
Jan 1, 2021, 12:24:32 PM1/1/21
to
On Fri, 1 Jan 2021 14:46:23 +0100
David Brown <david...@hesbynett.no> wrote:
> (Of course, for C++ you would make it a class, and put a std::array in
> the class instead of a C array.)

Or in C++ you could enforce the size as part of the type by preventing
array to pointer decay:

void clear_mac(uint8_t (&a)[6]);

Bonita Montero

unread,
Jan 1, 2021, 1:13:09 PM1/1/21
to
>> std::array is fixed size, too, but provides strict type safety, provides
>> bounds checking and allows the use of the standard algorithms library.

> If a piece of code is checking MAC addresses its probably very low level
> and could be in a tight loop where performance matters. Constantly doing
> bounds checking on a fixed size array in this situation is a waste of
> CPU cycles and needlessly slows the program down.

I think he has in mind the iterator-debugging facility when you arm
them with the proper #defines.

Ian Collins

unread,
Jan 1, 2021, 2:21:48 PM1/1/21
to
On 02/01/2021 05:18, spudisnot...@grumpysods.com wrote:
> On Fri, 1 Jan 2021 12:10:31 +0100
> Hergen Lehmann <hlehmann.e...@snafu.de> wrote:
>> Am 01.01.21 um 11:33 schrieb spudisnot...@grumpysods.com:
>>
>>> Jorgen Grahn <grahn...@snipabacken.se> wrote:
>>>> As an aside, a std::array<uint8_t, 6> would be a better choice for a
>>>
>>> Why? A MAC is a fixed size which will never change. A C array is efficient
>> and
>>> does the job.
>>
>> std::array is fixed size, too, but provides strict type safety, provides
>> bounds checking and allows the use of the standard algorithms library.
>
> If a piece of code is checking MAC addresses its probably very low level
> and could be in a tight loop where performance matters. Constantly doing
> bounds checking on a fixed size array in this situation is a waste of
> CPU cycles and needlessly slows the program down.

std::array is no less efficient in this situation. The bounds checking
is a compile time operation.

--
Ian.


Bonita Montero

unread,
Jan 1, 2021, 2:35:41 PM1/1/21
to
>> If a piece of code is checking MAC addresses its probably very low level
>> and could be in a tight loop where performance matters. Constantly doing
>> bounds checking on a fixed size array in this situation is a waste of
>> CPU cycles and needlessly slows the program down.

> std::array is no less efficient in this situation.
> The bounds checking is a compile time operation.

Bounds-checking can be compile-time only if the index is a constant.

Ben Bacarisse

unread,
Jan 1, 2021, 4:06:44 PM1/1/21
to
For the record, you can so something very similar in C:

void clear_mac(uint8_t (*a)[6])
{
memset(a, 0, sizeof *a);
}

--
Ben.

spudisnot...@grumpysods.com

unread,
Jan 2, 2021, 5:43:10 AM1/2/21
to
Please explain how bounds checking works at compile time for non literal
indexing.

David Brown

unread,
Jan 2, 2021, 7:24:14 AM1/2/21
to
I can't answer for exactly what Ian meant, but compilers regularly track
ranges that variables can have. And with an array of guaranteed known
size, they can warn you in at least some cases if you are going outside
that range. This is not the same as run-time access checks - it's just
a helpful warning for some kinds of errors that can be found cost-free.

A std::array also allows checked access (via the "at" operator), which
in general involves a run-time check. In many use-cases, however, the
compiler can see that the check will never fail and therefore skip it -
but that's by compiler optimisation, not guaranteed by design.

A compiler can do some of these checks even with a standard C array.
But it quickly loses guarantees about array sizes when they are passed
around as parameters - even when the parameter is written as an array
type rather than a pointer, the compiler can't rely on that information
and thus can't give helpful warnings for errors. Using a std::array, or
wrapping the C array in a struct (that is, in effect, how std::array
works) gives the compiler more information for better compile-time error
checking and better optimisation.

Alf P. Steinbach

unread,
Jan 2, 2021, 7:38:16 AM1/2/21
to
Uh, say what?

void foo( int (*a)[42] ) { // ... size of a is, not reliably known?

I would agree that this practice would give more verbose, harder to read
code, and possibly also less efficient code, and that it's very rare.

But that it wouldn't give the compiler reliable information?

Or are you talking about

void bar( int a[42] )

?

> Using a std::array, or
> wrapping the C array in a struct (that is, in effect, how std::array
> works) gives the compiler more information for better compile-time error
> checking and better optimisation.

Yes yes. :)


- Alf

David Brown

unread,
Jan 2, 2021, 9:07:22 AM1/2/21
to
I am talking about this second form - an array parameter rather than a
pointer to an array - since that's what the thread is about. The OP's
code was:

void clear_mac(uint8_t a[6]) ...

Certainly if you had a pointer to an array (of fixed size), as in your
"foo" (and Chris and Ben's posts), the size of the array is known.

(I assume you are talking about the size of the array. Even in the
"bar" example, the size of "a" is known to the compiler - it is the size
of a pointer. And the size of "*a" is also known - it is the size of an
int. Neither are the size of the array.)

spudisno...@grumpysods.com

unread,
Jan 2, 2021, 9:53:26 AM1/2/21
to
On Sat, 2 Jan 2021 13:23:57 +0100
David Brown <david...@hesbynett.no> wrote:
>On 02/01/2021 11:42, spudisnot...@grumpysods.com wrote:
>> Please explain how bounds checking works at compile time for non literal
>> indexing.
>>
>
>I can't answer for exactly what Ian meant, but compilers regularly track
>ranges that variables can have. And with an array of guaranteed known

Thats fine with simply for() loops where the loop variable(s) are unaffacted
by external influences because the compiler can calculate all possible value.
And in fact thats how we can have constexpr. But when those variables are
influenced from outside it quickly becomes an impossible task.

>size, they can warn you in at least some cases if you are going outside

Warnings along the lines of something may happen are generally fairly useless
IME.

Bo Persson

unread,
Jan 2, 2021, 10:04:08 AM1/2/21
to
On 2021-01-02 at 15:53, spudisno...@grumpysods.com wrote:
> On Sat, 2 Jan 2021 13:23:57 +0100
> David Brown <david...@hesbynett.no> wrote:
>> On 02/01/2021 11:42, spudisnot...@grumpysods.com wrote:
>>> Please explain how bounds checking works at compile time for non literal
>>> indexing.
>>>
>>
>> I can't answer for exactly what Ian meant, but compilers regularly track
>> ranges that variables can have. And with an array of guaranteed known
>
> Thats fine with simply for() loops where the loop variable(s) are unaffacted
> by external influences because the compiler can calculate all possible value.
> And in fact thats how we can have constexpr. But when those variables are
> influenced from outside it quickly becomes an impossible task.

If you let your array index be influenced from outside, you are probably
in for a surprise anyway. Especially if it happens in a way that even
the compiler cannot sort out.

spudisno...@grumpysods.com

unread,
Jan 2, 2021, 10:17:28 AM1/2/21
to
On Sat, 2 Jan 2021 16:03:51 +0100
Bo Persson <b...@bo-persson.se> wrote:
>On 2021-01-02 at 15:53, spudisno...@grumpysods.com wrote:
>> On Sat, 2 Jan 2021 13:23:57 +0100
>> David Brown <david...@hesbynett.no> wrote:
>>> On 02/01/2021 11:42, spudisnot...@grumpysods.com wrote:
>>>> Please explain how bounds checking works at compile time for non literal
>>>> indexing.
>>>>
>>>
>>> I can't answer for exactly what Ian meant, but compilers regularly track
>>> ranges that variables can have. And with an array of guaranteed known
>>
>> Thats fine with simply for() loops where the loop variable(s) are unaffacted
>> by external influences because the compiler can calculate all possible value.
>
>> And in fact thats how we can have constexpr. But when those variables are
>> influenced from outside it quickly becomes an impossible task.
>
>If you let your array index be influenced from outside, you are probably
>in for a surprise anyway. Especially if it happens in a way that even
>the compiler cannot sort out.

Depends. Anyway I was talking in general. For a MAC address the code to process
it would almost certainly be MAC specific and would have no reason to go off
the end of the array or to have checks for such so std::array would be overkill.

David Brown

unread,
Jan 2, 2021, 11:42:21 AM1/2/21
to
On 02/01/2021 15:53, spudisno...@grumpysods.com wrote:
> On Sat, 2 Jan 2021 13:23:57 +0100
> David Brown <david...@hesbynett.no> wrote:
>> On 02/01/2021 11:42, spudisnot...@grumpysods.com wrote:
>>> Please explain how bounds checking works at compile time for non literal
>>> indexing.
>>>
>>
>> I can't answer for exactly what Ian meant, but compilers regularly track
>> ranges that variables can have. And with an array of guaranteed known
>
> Thats fine with simply for() loops where the loop variable(s) are unaffacted
> by external influences because the compiler can calculate all possible value.
> And in fact thats how we can have constexpr. But when those variables are
> influenced from outside it quickly becomes an impossible task.

A large proportion of loops are made with a loop variable that is not
affected by "external influence". You don't /always/ have a counter
that starts at one number, then increments or decrements until it
reaches a target - but it is extremely common. Optimisations and static
analysis that make use of such situations are therefore useful.

>
>> size, they can warn you in at least some cases if you are going outside
>
> Warnings along the lines of something may happen are generally fairly useless
> IME.
>

Experiences and opinions vary. Good static analysis will not find all
possible bugs, but it can often find many types of mistake. I'd far
rather my compiler spotted the errors it can, as early as possible in
the write-compile-test-debug cycle.

Jorgen Grahn

unread,
Jan 2, 2021, 2:00:33 PM1/2/21
to
I know there's been a long discussion about this, but to answer the
"why?": as far as I'm concerned, std::array is (since 2011) the
default tool for fixed-size arrays. It's the /other/ solutions that
need a motivation.

Ian Collins

unread,
Jan 2, 2021, 4:09:04 PM1/2/21
to
Clearly it doesn't. That's why std::array has at().

My point was that std::array is no less efficient that a plain array
when used as one.

--
Ian.

Juha Nieminen

unread,
Jan 3, 2021, 4:32:46 AM1/3/21
to
Ian Collins <ian-...@hotmail.com> wrote:
> My point was that std::array is no less efficient that a plain array
> when used as one.

Also, like with other standard library containers, you'll get debug boundary
checking with gcc (and probably clang) if you compile with the option
-D_GLIBCXX_DEBUG, which you won't get for inbuilt arrays.

(Ok, I didn't actually check that -D_GLIBCXX_DEBUG also affects std::array,
but I would be very surprised if it didn't.)

(And yes, I'm aware of -fsanitize=address which ought to detect
out-of-bounds accesses of inbuilt arrays as well, but AFAIK it's not
as reliable, because with standard library containers and -D_GLIBCXX_DEBUG
the checks are added to the indexing code itself, checking against the
size of the array.)

Öö Tiib

unread,
Jan 3, 2021, 10:47:29 AM1/3/21
to
On Saturday, 2 January 2021 at 18:42:21 UTC+2, David Brown wrote:
> On 02/01/2021 15:53, spudisno...@grumpysods.com wrote:
> > On Sat, 2 Jan 2021 13:23:57 +0100
> > David Brown <david...@hesbynett.no> wrote:
> >> On 02/01/2021 11:42, spudisnot...@grumpysods.com wrote:
> >>> Please explain how bounds checking works at compile time for non literal
> >>> indexing.
> >>>
> >>
> >> I can't answer for exactly what Ian meant, but compilers regularly track
> >> ranges that variables can have. And with an array of guaranteed known
> >
> > Thats fine with simply for() loops where the loop variable(s) are unaffacted
> > by external influences because the compiler can calculate all possible value.
> > And in fact thats how we can have constexpr. But when those variables are
> > influenced from outside it quickly becomes an impossible task.
> A large proportion of loops are made with a loop variable that is not
> affected by "external influence". You don't /always/ have a counter
> that starts at one number, then increments or decrements until it
> reaches a target - but it is extremely common. Optimisations and static
> analysis that make use of such situations are therefore useful.

Note that vast majority of for loops in modern code are range-based
fors of C++11. So compiler already knows compile-time what that
range of std::array is. It has embarrassingly no ways to break that range
and so has no need to check it neither compile nor run time.

spudisno...@grumpysods.com

unread,
Jan 3, 2021, 11:23:37 AM1/3/21
to
On 2 Jan 2021 19:00:15 GMT
Jorgen Grahn <grahn...@snipabacken.se> wrote:
>On Fri, 2021-01-01, spudisnot...@grumpysods.com wrote:
>> Why? A MAC is a fixed size which will never change. A C array is
>> efficient and does the job.
>
>I know there's been a long discussion about this, but to answer the
>"why?": as far as I'm concerned, std::array is (since 2011) the
>default tool for fixed-size arrays. It's the /other/ solutions that
>need a motivation.

"In my opinion" is not an answer to Why.

spudisno...@grumpysods.com

unread,
Jan 3, 2021, 11:27:34 AM1/3/21
to
On Sun, 3 Jan 2021 10:08:44 +1300
Ian Collins <ian-...@hotmail.com> wrote:
>On 02/01/2021 23:42, spudisnot...@grumpysods.com wrote:
>>> std::array is no less efficient in this situation. The bounds checking
>>> is a compile time operation.
>>
>> Please explain how bounds checking works at compile time for non literal
>> indexing.
>
>Clearly it doesn't. That's why std::array has at().
>
>My point was that std::array is no less efficient that a plain array
>when used as one.

And also brings nothing to the table when dealing with fixed sized arrays
where no bounds checking needs to be done except probably binary bloat.

Öö Tiib

unread,
Jan 3, 2021, 12:09:18 PM1/3/21
to
The raw array brings nothing to table. Nothing. Have to
lose the size information or to use that uint8_t (*foo)[42] crap to pass
reference to it or have to wrap it into struct to pass by value. If done so
there are still no advantages, still as error-prone and ugly as it was.
Only excuse of advocating its usage is that you had the pain of using
it and want others to have same pain. IOW sadism of pathetic asshole.

spu...@isnotyourbuddy.co.uk

unread,
Jan 3, 2021, 12:22:24 PM1/3/21
to
On Sun, 3 Jan 2021 09:09:00 -0800 (PST)
=?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> wrote:
>On Sunday, 3 January 2021 at 18:27:34 UTC+2, spudisno...@grumpysods.com wrote:
>> On Sun, 3 Jan 2021 10:08:44 +1300
>> Ian Collins <ian-...@hotmail.com> wrote:
>> >On 02/01/2021 23:42, spudisnot...@grumpysods.com wrote:
>> >>> std::array is no less efficient in this situation. The bounds checking
>> >>> is a compile time operation.
>> >>
>> >> Please explain how bounds checking works at compile time for non literal
>> >> indexing.
>> >
>> >Clearly it doesn't. That's why std::array has at().
>> >
>> >My point was that std::array is no less efficient that a plain array
>> >when used as one.
>> And also brings nothing to the table when dealing with fixed sized arrays
>> where no bounds checking needs to be done except probably binary bloat.
>
>The raw array brings nothing to table. Nothing. Have to

Bringing something to the table implies something more than already existed.
The raw array is what already existed so by definition it wouldn't.

>lose the size information or to use that uint8_t (*foo)[42] crap to pass
>reference to it or have to wrap it into struct to pass by value. If done so
>there are still no advantages, still as error-prone and ugly as it was.

A MAC is fixed size, it NEVER changes. There is no need for anything other than
a C array.

>it and want others to have same pain. IOW sadism of pathetic asshole.

Ad homenim - the last resort of someone with no argument. Nice going.

Oh, and its spelt ARSEhole unless you're speaking in the american dialect.


Öö Tiib

unread,
Jan 3, 2021, 12:44:18 PM1/3/21
to
On Sunday, 3 January 2021 at 19:22:24 UTC+2, spu...@isnotyourbuddy.co.uk wrote:
> On Sun, 3 Jan 2021 09:09:00 -0800 (PST)
> =?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> wrote:
> >On Sunday, 3 January 2021 at 18:27:34 UTC+2, spudisno...@grumpysods.com wrote:
> >> On Sun, 3 Jan 2021 10:08:44 +1300
> >> Ian Collins <ian-...@hotmail.com> wrote:
> >> >On 02/01/2021 23:42, spudisnot...@grumpysods.com wrote:
> >> >>> std::array is no less efficient in this situation. The bounds checking
> >> >>> is a compile time operation.
> >> >>
> >> >> Please explain how bounds checking works at compile time for non literal
> >> >> indexing.
> >> >
> >> >Clearly it doesn't. That's why std::array has at().
> >> >
> >> >My point was that std::array is no less efficient that a plain array
> >> >when used as one.
> >> And also brings nothing to the table when dealing with fixed sized arrays
> >> where no bounds checking needs to be done except probably binary bloat.
> >
> >The raw array brings nothing to table. Nothing. Have to
> Bringing something to the table implies something more than already existed.
> The raw array is what already existed so by definition it wouldn't.

So there are no reasons to return to it ever as it has no advantages whatsoever.

> >lose the size information or to use that uint8_t (*foo)[42] crap to pass
> >reference to it or have to wrap it into struct to pass by value. If done so
> >there are still no advantages, still as error-prone and ugly as it was.
> A MAC is fixed size, it NEVER changes. There is no need for anything other than
> a C array.

Compiler has no concept of MAC. The std::array is in every sense as good or
better array than C array, also for MAC.

> >it and want others to have same pain. IOW sadism of pathetic asshole.
> Ad homenim - the last resort of someone with no argument. Nice going.
>
> Oh, and its spelt ARSEhole unless you're speaking in the american dialect.

You failed to show any other motivation of pushing inferior choice so I
guessed correctly? 😀 OK I can call you "pathetic arsehole" if you so wish.

Jorgen Grahn

unread,
Jan 3, 2021, 1:13:48 PM1/3/21
to
Correct. I'll reformulate:

I know there's been a long discussion about this, but to address the
"why?": as far as I'm concerned, std::array is (since 2011) the
default tool for fixed-size arrays. It's the /other/ solutions that
need a motivation.

Juha Nieminen

unread,
Jan 4, 2021, 2:13:47 AM1/4/21
to
If you need a two-dimensional array, is it guaranteed that there will be no
padding between the sub-arrays?

With inbuilt arrays there is such a guarantee.

spudisno...@grumpysods.com

unread,
Jan 4, 2021, 4:25:24 AM1/4/21
to
On Sun, 3 Jan 2021 09:44:02 -0800 (PST)
=?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> wrote:
>On Sunday, 3 January 2021 at 19:22:24 UTC+2, spu...@isnotyourbuddy.co.uk wr=
>ote:
>> Bringing something to the table implies something more than already exist=
>ed.=20
>> The raw array is what already existed so by definition it wouldn't.
>
>So there are no reasons to return to it ever as it has no advantages whatso=
>ever.

It has no disadvantages in this instance either and will probably produce a
smaller binary.

>> >lose the size information or to use that uint8_t (*foo)[42] crap to pass=
>=20
>> >reference to it or have to wrap it into struct to pass by value. If done=
> so=20
>> >there are still no advantages, still as error-prone and ugly as it was.
>> A MAC is fixed size, it NEVER changes. There is no need for anything othe=
>r than=20
>> a C array.
>
>Compiler has no concept of MAC. The std::array is in every sense as good or
>better array than C array, also for MAC.

Why is it better for a MAC where bound checking won't be required? Show me
what I've missed.

>You failed to show any other motivation of pushing inferior choice so I=20
>guessed correctly? =F0=9F=98=80 OK I can call you "pathetic arsehole" if yo=
>u so wish.

Pange see oma ajudeta baltlaste idikas sisse.

spudisno...@grumpysods.com

unread,
Jan 4, 2021, 4:28:47 AM1/4/21
to
On 3 Jan 2021 18:13:31 GMT
Jorgen Grahn <grahn...@snipabacken.se> wrote:
>On Sun, 2021-01-03, spudisno...@grumpysods.com wrote:
>> On 2 Jan 2021 19:00:15 GMT
>> Jorgen Grahn <grahn...@snipabacken.se> wrote:
>>>On Fri, 2021-01-01, spudisnot...@grumpysods.com wrote:
>>>> Why? A MAC is a fixed size which will never change. A C array is
>>>> efficient and does the job.
>>>
>>>I know there's been a long discussion about this, but to answer the
>>>"why?": as far as I'm concerned, std::array is (since 2011) the
>>>default tool for fixed-size arrays. It's the /other/ solutions that
>>>need a motivation.
>>
>> "In my opinion" is not an answer to Why.
>
>Correct. I'll reformulate:
>
> I know there's been a long discussion about this, but to address the
> "why?": as far as I'm concerned, std::array is (since 2011) the
> default tool for fixed-size arrays. It's the /other/ solutions that
> need a motivation.

When you actually have an answer get back to me.

Ben Bacarisse

unread,
Jan 4, 2021, 8:10:49 AM1/4/21
to
Juha Nieminen <nos...@thanks.invalid> writes:
The elements (in this case the sub-arrays) are guaranteed to be stored
contiguously in that &a[n] = &a[0] + n for all valid n. Therefore there
can't be any padding between the elements added simply because the
sub-arrays are in a containing array, but I can't find any guarantee
that

sizeof (std::array<T, N>) == N * sizeof (std::array<T, N>::value_type)

I.e. there may be padding at the end of a std::array (included in its
size) and therefore padding in some sense "between" the sub-arrays in a
std::array<std::array<T, N>, M>.

> With inbuilt arrays there is such a guarantee.

--
Ben.

Öö Tiib

unread,
Jan 4, 2021, 12:50:31 PM1/4/21
to
No, implementation may have more members at end of std::array
for example for debugging/trapping or whatever. So those elements may be
between sub-arrays oft that larger array. If you need guarantees about
size of standard layout class then always check it.

static_assert(sizeof(std::array<uint8_t,6>) == 6);

Check it about whatever standard layout type whose size matters as just
plain enum without underlying type specified may have different size
from platform to platform.

> With inbuilt arrays there is such a guarantee.

It is possibly beneficial for some case. If you really have that case then use
raw array indeed. But I would like to see performance issue reported first.
Programmers waste sometimes time pointlessly without benefit.

Manfred

unread,
Jan 6, 2021, 11:26:49 AM1/6/21
to
If the problem is about spurious padding, then it is likely not about
about performance; it's more probably about algorithmic simplicity or
compatibility with other parts of the system rather than data size per se.

Öö Tiib

unread,
Jan 7, 2021, 2:16:07 AM1/7/21
to
No, I have not seen any examples of compilers where that static_assert
actually fails so the issue of spurious padding is only allowed by standard
but no one is demonstrating it as real issue. But the array of arrays would
be bit bigger than raw multidimensional because of such padding. So
that (however little) resource/performance issue is certainly allowed by
standard. I would first like to see it demonstrated.

Compatibility when different modules want differently laid out data and
algorithmic simplicity and robustness are common problems in all software.
Can raw array somehow be used to solve those common and real problems?
I would love to see that demonstrated too as I do not even imagine it being
possible.
.

TDH1978

unread,
Jan 8, 2021, 6:48:21 PM1/8/21
to
On 2020-12-31 22:24:46 +0000, Keith Thompson said:

> That's odd. I don't see the same warning with gcc 10.2.0 (built from
> source) on Ubuntu with any argument for the -Wstringop-overflow= option.
>
> There is no gcc 10.2.1 release (yet).
>
> There *shouldn't* be a warning for that code. The int value 0 is
> converted to uint8_t before being stored in *a, so it won't write past
> the bounds of a 6-element array.
>
> Can you show a complete self-contained source file that exhibits the
> problem (what you posted won't compile because uint8_t is not defined),
> along with the exact command line you used to compile it and the output
> of "gcc --version"?

Sorry for my late response, but I've been trying, in vain, to get you a
self-contained source file. Every time I move the code around, the
warning dispappears. After much trial and error, I got to the point
where if I don't change anything in my project, and simply add the line
'std::string xyz = "abc";' in some totally unrelated function, the
warning in the clear_mac() function disappears. This leads me to
believe that this is indeed a compiler bug; I have no other explanation.

As I mentioned earlier, I did not get this warning with gcc/g++ 10.2.0.
I will wait for gcc/g++ 10.2.2 and try again. For now, I will live
with this warning.

Here is the compiler info you requested:

cmd> gcc --version
gcc (GCC) 10.2.1 20201125 (Red Hat 10.2.1-9)

Brian Wood

unread,
Jan 8, 2021, 11:25:51 PM1/8/21
to
I like hearing from him here. His perspective is
usually interesting.

Brian

Manfred

unread,
Jan 9, 2021, 1:15:13 PM1/9/21
to
As you say below, data layout is a much more common issue than a
performance hit being significant due to a few padding bytes. /If/
performance is suspect to be an actual problem, then demonstration
first, sure.

>
> Compatibility when different modules want differently laid out data and
> algorithmic simplicity and robustness are common problems in all software.
> Can raw array somehow be used to solve those common and real problems?
> I would love to see that demonstrated too as I do not even imagine it being
> possible.

One might think of some multidimensional (e.g. image) processing (or
compression) algorithm that assumes no padding. Then it is cleaner and
easier to use a raw array than an array of arrays, rather than rewriting
a possibly complex algorithm to handle some arbitrary padding between lines.
I mean, the sport of using std::array<std::array<...>, ...> wouldn't
justify such a rewrite per se.
Although, for this specific example, with a multidim raw array the UB
fluff of the C++ standard might get in the way, so the case is not
trivial either.

A probably more realistic example is some API between modules, possibly
even written in different languages, that exchange binary data whose
layout is part the contract. Then you want full control of such layout,
including padding.
In such scenario I believe you don't want a std::array as a member of
some struct that is passed through such interface. This is independent
of performance, of course.

Öö Tiib

unread,
Jan 10, 2021, 9:26:19 PM1/10/21
to
But that performance is the only issue there can be theoretically (but does
not exist in practice) that raw array can solve.

> > Compatibility when different modules want differently laid out data and
> > algorithmic simplicity and robustness are common problems in all software.
> > Can raw array somehow be used to solve those common and real problems?
> > I would love to see that demonstrated too as I do not even imagine it being
> > possible.
> One might think of some multidimensional (e.g. image) processing (or
> compression) algorithm that assumes no padding. Then it is cleaner and
> easier to use a raw array than an array of arrays, rather than rewriting
> a possibly complex algorithm to handle some arbitrary padding between lines.
> I mean, the sport of using std::array<std::array<...>, ...> wouldn't
> justify such a rewrite per se.

Can you cite such algorithms? I understand that it goes on and on about
that possible (but unexisting) padding that possibly complicates some possible
(but nonexistent) algorithms. I can't argue as I can't prove negative that
such algorithms do not exist. IOW my position stands firm, it is still not
demonstrated that such issues exist.

> Although, for this specific example, with a multidim raw array the UB
> fluff of the C++ standard might get in the way, so the case is not
> trivial either.
>
> A probably more realistic example is some API between modules, possibly
> even written in different languages, that exchange binary data whose
> layout is part the contract. Then you want full control of such layout,
> including padding.

If there is already present C interface then there are no std::arrays in
it possible. So you mean such. legacy interfaces by "algorithmic
simplicity"? Have to carefully static_assert bit widths of every type
if you just want to reinterpret_cast or memcpy some C++ classes
into there bluntly.

> In such scenario I believe you don't want a std::array as a member of
> some struct that is passed through such interface. This is independent
> of performance, of course.

The std::array can't be in C interface anyway. The data layout
issue is already within C++ where enum foo {}; can one byte wide type
and enum class moo {}; four bytes wide on very same compiler.

Manfred

unread,
Jan 11, 2021, 5:52:00 PM1/11/21
to
On 1/11/2021 3:26 AM, Öö Tiib wrote:
>> One might think of some multidimensional (e.g. image) processing (or
>> compression) algorithm that assumes no padding. Then it is cleaner and
>> easier to use a raw array than an array of arrays, rather than rewriting
>> a possibly complex algorithm to handle some arbitrary padding between lines.
>> I mean, the sport of using std::array<std::array<...>, ...> wouldn't
>> justify such a rewrite per se.
> Can you cite such algorithms?

Not from the top of my head, at this moment (and I am not going to try
any hard to remember one)

I understand that it goes on and on about
> that possible (but unexisting) padding that possibly complicates some possible
> (but nonexistent) algorithms. I can't argue as I can't prove negative that
> such algorithms do not exist. IOW my position stands firm, it is still not
> demonstrated that such issues exist.
>

I didn't mean to mount up a case on this.
We can leave it there.

TDH1978

unread,
Apr 30, 2021, 4:54:14 PM4/30/21
to
On 2020-12-31 22:24:46 +0000, Keith Thompson said:

> That's odd. I don't see the same warning with gcc 10.2.0 (built from
> source) on Ubuntu with any argument for the -Wstringop-overflow= option.
>
> There is no gcc 10.2.1 release (yet).
>
> There *shouldn't* be a warning for that code. The int value 0 is
> converted to uint8_t before being stored in *a, so it won't write past
> the bounds of a 6-element array.
>
> Can you show a complete self-contained source file that exhibits the
> problem (what you posted won't compile because uint8_t is not defined),
> along with the exact command line you used to compile it and the output
> of "gcc --version"?

I have upgraded to Fedora 34 and I can confirm that this warning does
not appear with gcc/g++ 11.0.1. This confirms my suspicion that this
was probably a compiler bug.

cmd> gcc --version
gcc (GCC) 11.0.1 20210324 (Red Hat 11.0.1-0)

wij

unread,
Apr 30, 2021, 10:13:34 PM4/30/21
to
On Friday, 1 January 2021 at 06:11:26 UTC+8, TDH1978 wrote:
> I have the following piece of code:
>
> void clear_mac(uint8_t a[6])
> {
> *a++ = 0;
> *a++ = 0;
> *a++ = 0;
> *a++ = 0;
> *a++ = 0;
> *a = 0;
> }
>
>
> This code compiled cleanly for the last 15 years. When I upgraded to
> the latest gcc/g++ 10.2.1 compiler on Fedora 33, I got the following
> warning:
>
> warning: writing 16 bytes into a region of size 6 [-Wstringop-overflow=]
>
>
> Does anyone know what the problem is? I tried using "0x00" instead of
> "0", to no avail. What "16 bytes" is the compiler referring to?

1. The result not duplicable in g++ 10.2.1 + Fedor33
2. The interpretation of array argument had been different in different versions
of g++ in my experience. (and the include files matter)
3. Writing a[0]=a[1]=a[2]=a[3]=a[4]=a[5]=0; seems better.
0 new messages