Saturday, January 9, 2021

Digest for comp.lang.c++@googlegroups.com - 10 updates in 1 topic

spudisnotyourbuddy@grumpysods.com: Jan 02 10:42AM

On Sat, 2 Jan 2021 08:21:28 +1300
>> 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.
 
Please explain how bounds checking works at compile time for non literal
indexing.
David Brown <david.brown@hesbynett.no>: Jan 02 01:23PM +0100

>> is a compile time operation.
 
> 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
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" <alf.p.steinbach+usenet@gmail.com>: Jan 02 01:37PM +0100

On 02.01.2021 13:23, David Brown wrote:
> 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.
 
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] )
 
?
 
> 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 <david.brown@hesbynett.no>: Jan 02 03:07PM +0100

On 02/01/2021 13:37, Alf P. Steinbach wrote:
 
> Or are you talking about
 
>     void bar( int a[42] )
 
> ?
 
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.)
 
spudisnotyourbud@grumpysods.com: Jan 02 02:53PM

On Sat, 2 Jan 2021 13:23:57 +0100
>> 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 <bo@bo-persson.se>: Jan 02 04:03PM +0100

> 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.
 
spudisnotyourbud@grumpysods.com: Jan 02 03:17PM

On Sat, 2 Jan 2021 16:03:51 +0100
 
>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 <david.brown@hesbynett.no>: Jan 02 05:42PM +0100

> 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.
Ian Collins <ian-news@hotmail.com>: Jan 03 10:08AM +1300

>> 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.
 
--
Ian.
Juha Nieminen <nospam@thanks.invalid>: Jan 03 09:32AM

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