EmbeddedRelated.com
Forums

Dimension of a matrix

Started by Tim Wescott March 23, 2017
On 26/03/17 18:55, Les Cargill wrote:
> David Brown wrote: >> On 25/03/17 21:17, Les Cargill wrote: >>> Hans-Bernhard Bröker wrote: >>>> Am 25.03.2017 um 19:12 schrieb Les Cargill: >>>>> David Brown wrote: >>>> >>>>> I could not tell you which versions of which compilers support >>>>> this, but in some toolchains, it's possible to specify the size >>>>> of an array being passed - void p(char x[256])... . >>>> >>>> All C compilers are actually required to allow you to pass a size >>>> like that. It doesn't have any effect whatsoever, though. Any >>>> number you put between those [] is really just decoration. These >>>> 4 function declarations are totally equivalent: >>>> >>>> void p(char x[256]); void p(char x[7]); void p(char x[]); void >>>> p(char *x); >>>> >>>> >>> >>> I recall (vaguely) code where sizeof(x) would return 256, but it's >>> a hazy memory. I don't remember the toolchain; probably latter day >>> MS VS stuff. >> >> That would be a broken compiler. >> > > It might have been a C++ toolchain. I don't recall. > > Those are out there for sure - although given all the furor over > Blind Pointers Will Be The End of Western Civilization these days.... > >>> >>> And even if it's just decoration, it preserves the size of the >>> array out of band. >>> >> >> Specifying the size here is just a comment. > > It is and it isn't. > >> And it is a dangerous >> comment, because it /looks/ like it might be something that the >> compiler will check, or that lets you use "sizeof" in the manner you >> describe - but it will not. In all the cases above, "x" is a pointer >> to char - /not/ an array. >> > > As a programmer, you have to check what things are. >
Section 6.7.6.3 "Function declarators (including prototypes)" of the C standards has paragraph 7: A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression. Using an array as a parameter type has /exactly/ the same effect as using a pointer. Applying "sizeof" to it returns the size of a pointer. C++ has the same thing (but without the option is using "static"). The wording in C++14 section 8.3.5 paragraph 5 is different but gives the same results. As a programmer, you absolutely should /not/ have to check that the compiler follows the fundamental rules of the language you are using. A compiler - C or C++ - which gives the "sizeof" a C array parameter as the sizeof the array rather than the size of the pointer, is /broken/. This is not an option, or a feature, or something that some compilers do - it is how C and C++ arrays work. And it is part of the reason for the introduction of std::array in C++.
On Sun, 26 Mar 2017 05:45:54 -0400, George Neuner wrote:

> On Sat, 25 Mar 2017 11:07:30 -0500, Tim Wescott <tim@seemywebsite.com> > wrote: > >>On Fri, 24 Mar 2017 23:14:36 -0400, George Neuner wrote: >> >>> On Fri, 24 Mar 2017 18:24:44 -0000 (UTC), Simon Clubley >>> <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote: >>> >>>>In the C++ library, it would be nice if the indexing operator most >>>>people would use by default, "[]", was the bounds checked one and the >>>>alternative indexing operator, "at()", was the non-bounds checked one. >>>>That way, you would have to do something unusual in your code to turn >>>>_off_ bounds checking instead of having to do something unusual in >>>>your code to turn _on_ bounds checking... >>> >>> Agreed. However, that would violate the C/C++ mantra that those who >>> do not want a feature should not have to pay for it. >>> >>> Strict bounds checking - particularly checks per dimension as opposed >>> to a single check that the overall target lies within the array - >>> would break some existing code. >>> [For the same reasons that pointers may be one-of before or after the >>> array, and iterators may be considered to point "between" elements.] >> >>We're talking about the C++ STL "array" class, which is defined as >>having a certain size, with no guarantees about what lies outside the >>range of the actual data. > > Yes. But not every array in C++ uses the STL class, and I was reacting > to Simon's comment about the '[]' index operator. > > It would be hopelessly confusing if the index operator of the array > class was checked, but the general (C compatible) index operator was > not. If the general operator were checked, undoubtedly some code would > break, and even though STL arrays are heap allocated with some overrun > slop, I suspect that checking the operator there also would break some > existing code. > [Not that breaking crappy code is a bad thing ... 8-) ]
Changing the behavior of the '[]' operator in native C++ code is a completely different class of change than changing the behavior of the '[]' operator in a library. The first requires a change to the underlying language definition, while the second is only a change to the library code. -- Tim Wescott Control systems, embedded software and circuit design I'm looking for work! See my website if you're interested http://www.wescottdesign.com
On 2017-03-25, Clifford Heath <no.spam@please.net> wrote:
> On 25/03/17 11:57, David Brown wrote: >> On 24/03/17 19:24, Simon Clubley wrote: >>> >>> Well, "type-safe" if you ignore the little fact that the normal >>> indexing operator "[]" is not bounds checked. :-) >> >> The types are safe - it's just the ranges that are not...
Some people would disagree with that definition of "type-safe". :-)
> > Beyond the bounds, you're looking at something which is > probably not the type you think you're looking at. That > is pretty-much the definition of "not type-safe". >
And that's exactly why they would disagree. If the bounds are not enforced, then it's not type-safe IMHO. Simon. -- Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP Microsoft: Bringing you 1980s technology to a 21st century world
On 2017-03-25, Clifford Heath <no.spam@please.net> wrote:
> On 25/03/17 11:57, David Brown wrote: >> On 24/03/17 19:24, Simon Clubley wrote: >>> >>> Well, "type-safe" if you ignore the little fact that the normal >>> indexing operator "[]" is not bounds checked. :-) >> >> The types are safe - it's just the ranges that are not...
Some people would disagree with that definition of "type-safe". :-)
> > Beyond the bounds, you're looking at something which is > probably not the type you think you're looking at. That > is pretty-much the definition of "not type-safe". >
And that's exactly why they would disagree. If the bounds are not enforced, then it's not type-safe IMHO. Simon. -- Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP Microsoft: Bringing you 1980s technology to a 21st century world
On 2017-03-26, Tim Wescott <tim@seemywebsite.com> wrote:
> > Changing the behavior of the '[]' operator in native C++ code is a > completely different class of change than changing the behavior of the > '[]' operator in a library. The first requires a change to the > underlying language definition, while the second is only a change to the > library code. >
In an ideal world, I wouldn't mind seeing the first one become reality either. Yes, it would break some bad code, but that existing code could easily be a CVE just waiting to happen. Simon. PS: And yes, I know about the C++ speed over safety design goals... :-) -- Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP Microsoft: Bringing you 1980s technology to a 21st century world
On Mon, 27 Mar 2017 00:09:48 +0000, Simon Clubley wrote:

> On 2017-03-26, Tim Wescott <tim@seemywebsite.com> wrote: >> >> Changing the behavior of the '[]' operator in native C++ code is a >> completely different class of change than changing the behavior of the >> '[]' operator in a library. The first requires a change to the >> underlying language definition, while the second is only a change to >> the library code. >> >> > In an ideal world, I wouldn't mind seeing the first one become reality > either. Yes, it would break some bad code, but that existing code could > easily be a CVE just waiting to happen.
I think that would have so many ugly tentacles extending into all parts of how C natively handles arrays that it would be a nightmare all around. Much better to just have people remember that '[]' is inherently unsafe, and Pay Attention, imho. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com I'm looking for work -- see my website!
On 27/03/17 01:53, Simon Clubley wrote:
> On 2017-03-25, Clifford Heath <no.spam@please.net> wrote: >> On 25/03/17 11:57, David Brown wrote: >>> On 24/03/17 19:24, Simon Clubley wrote: >>>> >>>> Well, "type-safe" if you ignore the little fact that the normal >>>> indexing operator "[]" is not bounds checked. :-) >>> >>> The types are safe - it's just the ranges that are not... > > Some people would disagree with that definition of "type-safe". :-) > >> >> Beyond the bounds, you're looking at something which is >> probably not the type you think you're looking at. That >> is pretty-much the definition of "not type-safe". >> > > And that's exactly why they would disagree. If the bounds are > not enforced, then it's not type-safe IMHO. >
Type safety is primarily a compile-time feature. The aim of type safety is to stop you trying to use the wrong "type" of "thing" (objects, classes, types, whatever) in the wrong place. And by restricting the operations you can do on your "things", you spot more mistakes at compile-time. A vital point is that type safety checks are free with respect to run-time costs. And your aim is to stop certain classes of error being /possible/. Checking the bounds of array accesses is primarily a run-time feature. There are run-time safety checks you can make - they are not type safety checks. They involve some run-time overhead, and you need run-time methods of dealing with detected errors - your aim is to detect certain classes of error when they happen, and stop them leading to worse problems. Sometimes there is a middle ground. The compiler may be able to check, at compile time, whether an array access is always safe, possibly safe, or always bad. It is certainly a good thing if the compiler can warn you on third case, and omit any run-time checks in the first case. You can argue that a std::array type is a type with a fixed known size, and therefore should not allow any access beyond its bounds. But actually it is defined as a type that wraps a C array with no run-time overheads for normal use, without run-time checking of bounds. It gives you methods for accessing the data, but there is a pre-condition on the [] operator that you are within the bounds of the array. This is a perfectly good way to define a type and its operations - type-safety does /not/ require run-time checking that pre-conditions to methods are met. That is the responsibility of the code using the type. Of course one could make a type for which bounds checking was part of the [] operator method specification. But even then, the check is not part of the type safety system because the index is not part of a type, and the check is not at compile-time. If you want that kind of type safety, use a std::tuple and get<i> functions for access - /those/ accesses are type checked.
On 27/03/17 18:51, David Brown wrote:
> On 27/03/17 01:53, Simon Clubley wrote: >> On 2017-03-25, Clifford Heath <no.spam@please.net> wrote: >>> On 25/03/17 11:57, David Brown wrote: >>>> On 24/03/17 19:24, Simon Clubley wrote: >>>>> >>>>> Well, "type-safe" if you ignore the little fact that the normal >>>>> indexing operator "[]" is not bounds checked. :-) >>>> >>>> The types are safe - it's just the ranges that are not... >> >> Some people would disagree with that definition of "type-safe". :-) >> >>> >>> Beyond the bounds, you're looking at something which is >>> probably not the type you think you're looking at. That >>> is pretty-much the definition of "not type-safe". >>> >> >> And that's exactly why they would disagree. If the bounds are >> not enforced, then it's not type-safe IMHO. >> > > Type safety is primarily a compile-time feature.
Sorry, but you can't just redefine "type safety" to mean "static type safety" and exclude "dynamic type safety". I get it, static >> dynamic, but they're both about type safety. Clifford Heath.
On 27/03/17 11:19, Clifford Heath wrote:
> On 27/03/17 18:51, David Brown wrote: >> On 27/03/17 01:53, Simon Clubley wrote: >>> On 2017-03-25, Clifford Heath <no.spam@please.net> wrote: >>>> On 25/03/17 11:57, David Brown wrote: >>>>> On 24/03/17 19:24, Simon Clubley wrote: >>>>>> >>>>>> Well, "type-safe" if you ignore the little fact that the normal >>>>>> indexing operator "[]" is not bounds checked. :-) >>>>> >>>>> The types are safe - it's just the ranges that are not... >>> >>> Some people would disagree with that definition of "type-safe". :-) >>> >>>> >>>> Beyond the bounds, you're looking at something which is >>>> probably not the type you think you're looking at. That >>>> is pretty-much the definition of "not type-safe". >>>> >>> >>> And that's exactly why they would disagree. If the bounds are >>> not enforced, then it's not type-safe IMHO. >>> >> >> Type safety is primarily a compile-time feature. > > Sorry, but you can't just redefine "type safety" to mean "static > type safety" and exclude "dynamic type safety". > > I get it, static >> dynamic, but they're both about type safety. >
Fair enough, I suppose. C++ supports dynamic type safety too, such as the dynamic_cast operator. But static type safety is the main mechanism for type safety in C++. std::array is defined to be a type with greater static type safety compared to standard C/C++ arrays - it knows its size, does not decay to a pointer, etc. It is not defined to have run-time bounds checking by default - but you have the option if you want (with the "at" method). Type safety - dynamic or static - does not mean preventing any possible errors. It merely means making it hard to accidentally make errors from mixing up types - and it is a balance between safety, convenience (in writing the code) and efficiency (code size and speed at run-time). It is not an absolute term (at least, not in real-world programs in real-world programming languages). It would be fair to say that an array container that always checked its bounds is /safer/ than std::array, and is more "type safe". But it could never be completely type safe - not in C++, where you have reinterpret_cast, unions, void*, memcpy, and all sorts of other ways to cheat on type safety.
On 27/03/17 01:43, Tim Wescott wrote:
> On Mon, 27 Mar 2017 00:09:48 +0000, Simon Clubley wrote: > >> On 2017-03-26, Tim Wescott <tim@seemywebsite.com> wrote: >>> >>> Changing the behavior of the '[]' operator in native C++ code is a >>> completely different class of change than changing the behavior of the >>> '[]' operator in a library. The first requires a change to the >>> underlying language definition, while the second is only a change to >>> the library code. >>> >>> >> In an ideal world, I wouldn't mind seeing the first one become reality >> either. Yes, it would break some bad code, but that existing code could >> easily be a CVE just waiting to happen. > > I think that would have so many ugly tentacles extending into all parts > of how C natively handles arrays that it would be a nightmare all around. > > Much better to just have people remember that '[]' is inherently unsafe, > and Pay Attention, imho.
And my, that theory has worked out well in practice, hasn't it. :(