- Strange compiler warning... - 10 Updates
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:
Post a Comment