limitations of casts, pointer and function declarartions...

Thomas M. Breuel breuel at harvard.ARPA
Mon Oct 29 21:12:18 AEST 1984


In reply to Doug Gwyn's comments:

>> 	int x;
>> 	char *y;
>> /*### [cc] illegal lhs of assignment operator = %%%*/
>> 	(char *)x = y;
>
>You need an lvalue, not an expression, on the LHS.

K&R 'defines' an lvalue as an 'expression referring to an object'.
and an object as a 'manipulable region of storage'. '(char *)x' is a
perfectly good lvalue: it refers to the object 'x' considered as
a pointer to a character.

>> typedef ref *ref;
>
>All types must reduce to a basic type (void, char, short, int, long,
>float, double, struct/union) plus some number of operators (*, (), []).

I think the semantics of this typedef are clear (and can be defined
easily). Also, the above typedef is in no way different from the
structure declaration 'struct foo {foo *ref;};'. FTSO consistency and
considering its usefulness, I think the above typedef should be
permitted. (BTW, a struct/union is not a basic type either).

>> The point is that if a pointer of this type is dereferenced, it should
>> have the same type again.  In addition, the type should be cast'able
>> to/from integer, and the size associated with it should be that of a
>> single pointer of its kind.
>
>At present, the generic pointer type is (char *) (ANSI will probably
>change this to (void *)).  A (char *) is castable to a (long) and back
>without loss of information (note: NOT always to an (int)).  By using
>appropriate type casts you can use the contents of a (char *) or (long)
>for other purposes.

Not quite: let p be defined as 'char *p;'. '((long *)p)++' does not
work (see above). As I said, I don't want a 'generic' or 'untyped'
pointer, but a pointer to something which has the same length and type
as the pointer itself, so that I can use dereferencing and additive
assignment operators on it freely. (BTW, I don't think that an untyped
pointer is very useful: you might as well use a pointer to a character
if you don't care about the size associated with some pointer).

>C is a typed language.  To implement another, untyped, language (or one
>with types that do not reduce to basic types) in C you must pick a
>definite C data type to represent objects in the other language (in this
>case, ProLog).  Then you need to coerce data into the appropriate types
>via typecasts when implementing recursive types etc.  C lets you do this
>but you have to explicitly indicate that you are playing tricks with data
>types.  (With some C implementations you can be pretty sloppy, but for
>portable code follow the type rules and run everything past "lint".)

No, recursive types are legal an possible in 'C'. Take the above
example 'struct foo {struct foo *ref;};'. Unfortunately, this does not
help to implement recursive pointers easily, since this structure
cannot be cast directly to/from an integer type, and since it is even
more inconvenient to include the suffix '.ref' everywhere than it is to
cast explicitely everywhere.

Also, Pascal, which is doubtlessly a strongly typed language, does
permit a type definition like 'type ref= ^ref;' and handles it
correctly.  Strong typing is not contradicted by allowing a recursive
pointer definition.  (BTW, I don't think that one can be dogmatic about
a typing system as messy as that of 'C').

Again, my question is: given the 4.2 cpp and ccom, what is the most
convenient way (i.e. requiring the least number of typecasts) of
dealing with the case the 99% of all pointers give another pointer of
their own kind upon dereferencing?

Sorry for not expressing myself more clearly in the first posting.

						Thomas M. Breuel
						breuel at harvard.arpa



More information about the Comp.lang.c mailing list