[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: OT: Language War (Re: "C" Manual)



On Sat, Jan 05, 2002 at 09:38:01PM -0800, Erik Steffl wrote:
| dman wrote:
...
| > In C/C++ there is an invariant on strings ("char*", which is
| > essentially equivalent to "char[]") that they end with a NUL byte.
| 
|   no, that's not true.

It is true.  A type is more than the name a compiler gives it.  A type
also includes invariants and pre- and post-conditions of all
operations on it. 

|   char* or char[] are arrays. SOME functions use them in a way that
| requires '\0' character to be somewhere within allocated space for given
| array. but that's strictly requirement of value for some pecific
| functions, it has nothing to do with definition of language.
| 
|   it is perfectly legal to use character arrays that have no '\0'
| character (just don't use them in functions that assume the '\0' to be
| last character to use).

I agree with you that C/C++ compilers have a limited view on types and
don't catch errors like the given example where an array of characters
(that fails to meet the invariants on strings) is handed to a function
that requires (a precondition) a valid string.  Certainly character
arrays that aren't strings are legal data types, and you can create
your own string type.  Remember, though, that a type is more than a
name.

| > The invariant is an implicit precondition for the operation that was
| > performed.  The coder above broke that invariant, which means that the
| > precondition for the operation wasn't met, and the result is
| > "undefined" (a segfault, if you're lucky).
| 
|   yes, but that's what was said before. it doesn't have anything to do
| with types, it is simply bad value.

A "bad value" is one which fails to meet the invariants of the given
type, thus it is not "of that type".

| just like you cannot divide by zero.

A precondition to integer and floating point division is that the
denominator != 0.  If you fail to meet that precondition, the results
are undefined.  (As a prof of mine likes to say "all bets are off")

| > A better approach is to use classes with set interfaces to ensure that
| > any invariants on the type can't be broken, but C doesn't have such
| > capabilities.  It is also better if the system can perform those
| > checks for you, but it isn't always possible or feasible.
| > 
| > Eiffel provides a way for you to specify the invariants,
| > preconditions, and postconditions of portions of code (classes and
| > methods); but even so, not everything can be checked.
| 
|   that's all good, but the point here is that it's not type issue. the
| type of variable and the domain of valid values are two separate issues
| (well, you could define a new type where type would be the same as valid
| domain but it's not always possible).

It is a type issue.  As stated above a type is more than a name; it
also includes all the invariants that must be kept.

| > | > Therefore, I claim that type safety is a more fundamental concept than
| > | > resource mangement.
| > |
| > |   well, why?
| > 
| > See the above discussion of invariants, preconditions, and
| > postconditions.  Those are part of a "type", but have little to do
| > with resource management.
| 
|   above discussion is irrelevant to the issue at hand, there is no such
| type in C and the preconditions are only for specific functions (and are
| more part of specifying valid domain that valid types).
| 
|   if you don't believe it, just check it again - there is no type error
| in the C code quoted above. it's the value that's wrong for given
| function (operator <<).

I agree that the C compiler has an incomplete notion of 'types' (based
solely on name) which is why *it* doesn't tell you that you made an
error.

-D

-- 

Python is executable pseudocode. Perl is executable line noise.



Reply to: