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

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



dman wrote:
> 
> 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

  the type in C is only what type in C is. what the type is in your head
is irrelevant.

> also includes invariants and pre- and post-conditions of all
> operations on it.

  no, not in C.

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

  the string is convenient name for certain values of character array.
it's not a type.

> your own string type.  Remember, though, that a type is more than a
> name.

  for you, maybe. for C, not.

> | > 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".

  and which C type would that be?

> | 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")

  that's precondition of operation, not of type. notice that division
accepts any two numbers (again, think of types and domains of valid
values)

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

  type is what given language considers a type. not what you (or I)
consider a type. and also, you need to differentiate between types and
domains of valid values (not sure if these are correct english math
terms but think of your math classes (mathematical analysis) and I'm
quite sure you'll know what that menas - most of math fairy tales starts
with: for all x, y from N, where x<y (N is type, condition after where
specifies domain of valid values))

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

  yes, but:

  solely on name: not sure what you mean here, you refer to types by
names in all languages, it's just that definition of type might be more
complicated, in C you have certain primitive types that you can use to
construct new type given specific operations (typedef, struct, ...), in
some languages you might have a way to specify type using 'procedural'
conditions.

  in the example above (sort of, it's not quoted anymore) there is only
one variable involved and so you can try to make it an issue of type,
why is it wrong and why you have to consider types and domains of valid
values separately is clear when using more than one variable.

  imagine that you have a binary operator that only works for certain
values of parameters:

int operator * (int i, int j)
{
  if(i<j) segfault()
  else    return (double)i * (double)j;
}

  is there any way to specify types of i and j so that it never
segfaults? no. in general you have to consider the values separately
from type. and IMO it makes perfect sense in case of 'string' in C -
it's just a special value (special for certain functions, NOT for C
language) of character array.

	erik



Reply to: